Scalar::Defer(3pm)
π Scalar::Defer β the lazy-evaluation baddie of Perl π
User Contributed Perl Documentation Β· it's a 3pm page bestie, we're in the big leagues now
β¨ NAME β¨
Scalar::Defer β Lazy evaluation in Perl. That's it, that's the whole vibe. π¦
πΈ SYNOPSIS πΈ
use Scalar::Defer; # exports 'defer', 'lazy' and 'force'
my ($x, $y);
my $dv = defer { ++$x }; # a deferred value (not memoized)
my $lv = lazy { ++$y }; # a lazy value (memoized)
print "$dv $dv $dv"; # 1 2 3
print "$lv $lv $lv"; # 1 1 1
my $forced = force $dv; # force a normal value out of $dv
print "$forced $forced $forced"; # 4 4 4
π DESCRIPTION π
Okay so this module exports two functions, defer and lazy, and what they do is build values that get figured out on demand β like, not right now, whenever somebody actually needs them. It also exports a force function so you can make a deferred value spill its secrets. π
π defer {...}
Gives you a block or a code reference, hands you back a deferred value. Every single time that value gets demanded, the block runs again and gives you a fresh result. No caching, no storing, just fresh-out-the-oven every time. β¨
π lazy {...}
Same energy as defer, except the value gets computed at most once. After that, every later evaluation just grabs the cached result and chills. π§
π force $value
Forces a deferred value to actually evaluate so you get a normal value back. And if $value was already a normal value? Then force is just like "okay bestie here you go" and returns it unchanged. π«Ά
π is_deferred $value
Tells you whether the thing you passed in is a deferred value or not. (Heads up: lazy values are deferred too, they're the same family.) π
The is_deferred function is not exported by default β if you want it, you gotta name it explicitly in the import list. No sneaking in. π
π NOTES π
Deferred values are not considered objects β like, ref on them returns 0. But plot twist, you can still call methods on them! And when you do, the invocant is always the forced value. Main character behavior honestly. π
Unlike the tie-based Data::Lazy, this module operates on values, not variables. So assigning another value into $dv and $lv up there will simply replace the value β it will not trigger a STORE method call. No drama, no hook, just a swap. π
Similarly, assigning $dv or $lv into another variable will not trigger a FETCH method β it just propagates the deferred value over without evaluating it. And this is why it's so much faster than a tie-based implementation. Even in the absolute worst case scenario, where it gets immediately forced right after creation, this module is still twice as fast than Data::Lazy. Ate. π₯
π CAVEATS π
Bad things may happen if this module interacts with any other code which fiddles with package 0. Like, genuinely bad. Be careful out there. π
Also, performance of creating new deferred or lazy values can be quite poor under perl 5.8.9. Why? It's due to a bugfix since 5.8.8, where re-blessing an overloaded object caused bad interactions with other references to the same value. 5.8.9's solution involves walking the arenas to find all other references to the same object, which can cause bless (and thus defer in Scalar::Defer) to be up to three orders of magnitude slower than usual. Three. Orders. Of. Magnitude. π perl 5.10.0 and higher do not suffer from this problem, so if you're on 5.8.9β¦ bestie, upgrade. π
π¦ SEE ALSO π¦
- Data::Thunk β it implements
lazyvalues that can replace themselves upon forcing, leaving a minimal trace of the thunk, with some sneaky XS magic in Data::Swap. Iconic, honestly. β¨
π AUTHORS π
Audrey Tang <cpan@audreyt.org> β the legend herself π
π COPYRIGHT π
Copyright 2006, 2007, 2008, 2009 by Audrey Tang <cpan@audreyt.org>.
This software is released under the MIT license cited below. π
πΈ The "MIT" License πΈ
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
And that's the whole page, bestie! πΈ This one shipped as part of perl v5.36.0, dated 2022-12-12 β so yeah, go forth and defer responsibly. Periodt. πβ¨
π¦ where this page comes from
- debian bookworm: libscalar-defer-perl 0.23-3 Β· MIT
- debian trixie: libscalar-defer-perl 0.23-3 Β· MIT
- ubuntu noble: libscalar-defer-perl 0.23-3 Β· MIT
- ubuntu resolute: libscalar-defer-perl 0.23-3 Β· MIT
- ubuntu stonking: libscalar-defer-perl 0.23-3 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms