Data::Lazy.pm - ``lazy'' variables.
version 0.5
(rem: Obsoletes Lazy.pm)
use Data::Lazy variablename => 'code', LAZY_READONLY ; use Data::Lazy variablename => \&fun; use Data::Lazy '@variablename' => \&fun;
A very little module for simulating lazines in perl. It provides scalars that are ``lazy'', that is their value is computed only if necessary and at most once.
tie $variable_often_unnecessary, Data::Lazy, sub {a function taking a long time} [, $store_options];
tie $var, Data::Lazy, 'a string containing some code' [, $store_options];
use Data::Lazy variablename => 'code' [, $store_options];
use Data::Lazy '$variablename' => \&function [, $store_options];
The first time you access the variable, the code gets executed and the result is saved for later as well as returned to you. Next accesses will use this value without executing anything.
You may specify what will happen if you try to reset the variable. You may either change the value or the code.
1. tie $var, Data::Lazy, 'sleep 1; 1'; # or tie $var, Data::Lazy, 'sleep 1; 1', LAZY_STOREVALUE; $var = 'sleep 2; 2'; print "'$var'\n";
will return
'sleep 2; 2'
2. tie $var, Data::Lazy, 'sleep 1; 1', LAZY_STORECODE;
will return
'2'
after 2 seconds of waiting.
3. tie $var, Data::Lazy, 'sleep 1; 1', LAZY_READONLY; $var = 'sleep 2; 2'; print "'$var'\n";
Will give you an error message : Modification of a read-only value attempted at ...
If you tie the variable with LAZY_STORECODE option and then undef the variable, only the stored value is forgoten and next time you access this variable, the code is reevaluated.
It's possible to create several variables in one ``use Data::Lazy ...'' statement.
Eg.
tie @variable, Data::Lazy, sub {a function taking a long time};
tie @var, Data::Lazy, 'a string containing some code';
use Data::Lazy '@variablename' => \&function;
The first time you access some item of the list, the code gets executed with $_[0] being the index and the result is saved for later as well as returned to you. Next accesses will use this value without executing anything.
You may change the values in the array, but there is no way (currently) to change the code :-(
Ex. tie @var, Data::Lazy, sub {$_[0]*1.5+15}; print ">$var[1]<\n"; $var[2]=1; print ">$var[2]<\n";
tie @fib, Data::Lazy, sub { if ($_[0] < 0) {0} elsif ($_[0] == 0) {1} elsif ($_[0] == 1) {1} else {$fib[$_[0]-1]+$fib[$_[0]-2]} }; print $fib[15];
Currently it's next to imposible to change the code to be evaluated
in a Data::Lazy array. Any options you pass to tie()
are ignored.
Due to current suport for tieing arrays in Perl (or lack thereof) you have to use tied(@a)->{'size'} to get the size of the array, if you use usual scalar(@a) you will get zero! :-(
Eg.
tie %variable, Data::Lazy, sub {a function taking a long time};
tie %var, Data::Lazy, 'a string containing some code';
use Data::Lazy '%variablename' => \&function;
The first time you access some item of the hash, the code gets executed with $_[0] being the key and the result is saved for later as well as returned to you. Next accesses will use this value without executing anything.
If you want to get or set the code that's being evaluated for the previously unknown items you will find it in $variable{$;}. If you change the code all previously computed values are forgotten.
Ex. tie %var, Data::Lazy, sub {reverse $_[0]}; print ">$var{'Hello world'}<\n"; $var{Jenda}='Jan Krynicky'; print ">$var{'Jenda'}<\n"; $fun = $var{$;}; $var{$;} = sub {$_ = $_[0];tr/a-z/A-Z/g;$_}; print ">$var[2]<\n";
! If you write something like
while (($key,$value) = each %lazy_hash) { print " $key = $value\n"; # };
only the previously fetched items are returned. Otherwise the listing would be infinite :-)
If you want to access the code or value stored in the variable directly you may use
${tied $var}{code} and ${tied $var}{value} # scalar $var ${tied @var}{value}[$i] # array @var ${tied %var}{value}{$name} # hash %var
This way you may modify the code even for arrays and hashes, but be very careful with this. Of course if you redefine the code, you'll want to undef the {value}!
There are two more internal variables:
${tied $var}{type} 0 => scalar 1 => array 2 => hash ${tied $var}{store} 0 => LAZY_STOREVALUE 1 => LAZY_STORECODE 2 => LAZY_READONLY
If you touch these, prepare for very strange results!
1. use Data::Lazy; tie $x, Data::Lazy, sub{sleep 3; 3}; # or # use Data::Lazy '$x' => sub{sleep 3; 3};
print "1. "; print "$x\n"; print "2. "; print "$x\n";
$x = 'sleep 10; 10';
print "3. "; print "$x\n"; print "4. "; print "$x\n";
2. (from Win32::FileOp) tie $Win32::FileOp::SHAddToRecentDocs, Data::Lazy, sub { new Win32::API("shell32", "SHAddToRecentDocs", ['I','P'], 'I') or die "new Win32::API::SHAddToRecentDocs: $!\n" }; ...
Please note that there are single guotes around the variable names in ``use Data::Lazy '...' => ...'' statements. The guotes are REQUIRED as soon as you use any variable type characters ($, @ or %)!
Jan Krynicky <Jenda@Krynicky.cz>
Copyright (c) 2001 Jan Krynicky <Jenda@Krynicky.cz>. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.