Data::Thunk - A sneakier Scalar::Defer ;-)
use Data::Thunk qw(lazy);
my %hash = (
foo => lazy { $expensive },
);
$hash{bar}{gorch} = $hash{foo};
$hash{bar}{gorch}->foo; # vivifies the object
warn overload::StrVal($hash{foo}); # replaced with the value
This is an implementation of thunks a la the Scalar::Defer manpage, but uses
the Data::Swap manpage and assignment to $_[0] in order to leave a minimal trace of the thunk.
In the case that a reference is returned from lazy { } the Data::Swap manpage can
replace the thunk ref with the result ref, so all the references that pointed
to the thunk are now pointing to the result (at the same address).
If a simple value is returned then the thunk is swapped with a simple scalar
container, which will assign the value to $_[0] on each overloaded use.
In this particular example:
my $x = {
foo => lazy { "blah" },
bar => lazy { [ "boink" ] },
};
$x->{quxx} = $x->{foo};
$x->{gorch} = $x->{bar};
warn $x->{bar};
warn $x->{foo};
warn $x->{quxx};
use Data::Dumper;
warn Dumper($x);
The resulting structure is:
$VAR1 = {
'bar' => [ 'boink' ],
'foo' => 'blah',
'gorch' => $VAR1->{'bar'},
'quxx' => 'blah'
};
Whereas with the Scalar::Defer manpage the trampoline objects remain:
$VAR1 = {
'bar' => bless( do{\(my $o = 25206320)}, '0' ),
'foo' => bless( do{\(my $o = 25387232)}, '0' ),
'gorch' => $VAR1->{'bar'},
'quxx' => $VAR1->{'foo'}
};
This is potentially problematic because reftype in the Scalar::Util manpage and blessed in the Scalar::Util manpage can't be fooled. With the Data::Thunk manpage the problem still exists before values are vivified, but not after.
Furthermore this module uses the UNIVERSAL::ref manpage instead of blessing to 0.
Blessing to 0 pretends that everything is a non ref (ref($thunk) returns
the name of the package, which evaluates as false), so deferred values that
become objects don't appear to be as such.
Create a new thunk.
Creates a thunk that is expected to be an object.
If the class attribute is provided then isa and can will work as class
methods without vivifying the object.
Any other attributes in %attrs will be used to shadow method calls. If the keys are code references they will be invoked, otherwise they will be simply returned as values. This can be useful if some of your object's properties are known in advance.
A specialization on lazy_object that can call a constructor method based on
a class for you. The constructor and args arguments (method name or code
ref, and array reference) will be removed from %args to create the thunk. They
default to new and an empty array ref by default. Then this function
delegates to lazy_object.
Vivify the value and return the result.
the Scalar::Defer manpage, the Data::Lazy manpage, the Data::Swap manpage, the UNIVERSAL::ref manpage.
This module is maintained using Darcs. You can get the latest version from
http://nothingmuch.woobling.org/code, and use darcs send to commit
changes.
Yuval Kogman <nothingmuch@woobling.org>
Copyright (c) 2008 Yuval Kogman. All rights reserved
This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.