I have a variable that I need to pass to a subroutine. It is very possible that the subroutine will not need this variable, and providing the value for the variable is expensive. Is it possible to create a "lazy-loading" object that will only be evaluated if it is actually being used? I cannot change the subroutine itself, so it must still look like a normal Perl scalar to the caller.
You'll want to look at Data::Lazy and Scalar::Defer. Update: There's also Data::Thunk and Scalar::Lazy.
I haven't tried any of these myself, but I'm not sure they work properly for an object. For that, you might try a Moose class that keeps the real object in a lazy attribute which handles
all the methods that object provides. (This wouldn't work if the subroutine does an isa
check, though, unless it calls isa
as a method, in which case you can override it in your class.)
Data::Thunk
is the most transparent and robust way of doing this that i'm aware of.
However, I'm not a big fan of it, or any other similar modules or techniques that try to hide themself from the user. I prefer something more explicit, like having the code using the value that's hard to compute simply call a function to retrieve it. That way you don't need to precompute your value, your intent is more clearly visible, and you can also have various options to avoid re-computing the value, like lexical closures, perl's state variables, or modules like Memoize
.
I would suggest stepping back and rethinking how you are structuring your program. Instead of passing a variable to a method that it might not need, make that value available in some other way, such as another method call, that can be called as needed (and not when it isn't).
In Moose, data like this is ideally stored in attributes. You can make attributes lazily built, so they are not calculated until they are first needed, but after that the value is saved so it does not need to be calculated a second time.