###################################################################### # Week 9 - Tied variables # From http://www-128.ibm.com/developerworks/library/l-cptied.html?ca=dnt-43 # CharArray allows for a scalar string to be tied to an array # so it can be manipulated like a python string. use Tie::CharArray; my $foobar = 'a string'; tie my @foo, 'Tie::CharArray', $foobar; $foo[0] = 'A'; # $foobar = 'A string' push @foo, '!'; # $foobar = 'A string!' ###################################################################### # Date.pm: Package for tied Dates # # Internally, the dates are stored as Year, Month, Day, but # when FETCHED, they are the integer number of days since the # epoc of January 1, 1900. This integer form allow for easier # date arithmetic. # package Date; # The use line below is like python's 'from package import resources' # Date::Calc allows for calculations to be performed on dates and is # available at http://search.cpan.org/dist/Date-Calc/ use Date::Calc qw(Delta_Days Add_Delta_Days Day_of_Week); # directive for using strict error checking, requires variables to be # declared with my, fully qualified or imported use strict; # TIESCALAR can be thought of as the constructor for a tied variable # called when the 'tie' function is invoked on a variable for this class sub TIESCALAR { # Bless a new anonymous hash. This hash stores the instance variables # Note that shift is called without any parameters, so by default it # uses @_, the arguments of the tie function call. my $self = bless{}, shift; $self->{Year} = shift; # initialize the hash with the given parameters $self->{Month} = shift;# of year, month and day $self->{Day} = shift; # Day of week is calculated from the given year, month, and day $self->{DoW} = Day_of_Week($self->{Year}, $self->{Month}, $self->{Day}); return $self; } # STORE is called when a tied variable is on the LHS of an assignment # the given value is a single integer representing of the number of days # since January 1, 1900. This is converted into the year, month, day values # that are stored internally. sub STORE { my ($self, $val) = @_; # STORE args are tied variable and value to store my ($y, $m, $d); # calculate the year, month, day values ($y, $m, $d) = Add_Delta_Days(1900, 1, 1, $val); # update the internal representation $self->{Year} = $y; $self->{Month} = $m; $self->{Day} = $d; $self->{DoW} = Day_of_Week($self->{Year}, $self->{Month}, $self->{Day}); } # FETCH is called when a tied variable is read. The internal representation # of year, month, day is convereted into an integer equal to the number # of days since January 1, 1900 sub FETCH { my $r = shift; # FETCH arg is the tied variable my $diff = Delta_Days(1900, 1, 1, $r->{Year}, $r->{Month}, $r->{Day}); return $diff } # print the date information as a string like "January 1, 1900" sub printdate{ my $s = shift; my @monthnames = ("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); my @dayofweeknames = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"); print "$dayofweeknames[$s->{DoW}], $monthnames[$s->{Month}-1] $s->{Day}, $s->{Year}\n"; } 1; ###################################################################### # testDate.pl use Date; tie $x, 'Date', 2005, 06, 01; # tied allows for access to underlying object that is represented by # the variable bound with tie $y = tied $x; $y->printdate; print "x is $x\n"; # referencing the tied variable x will return an integer $x += 60; # 60 days from today Date::printdate($y); # printdate can also be used as a class method $x += 365; # 1 year from today $y->printdate;