Perl, evaluate a line lazily

Consider the following Perl code.

#!/usr/bin/perl use strict; use warnings; $b="1"; my $a="${b}"; $b="2"; print $a; 

script obviously outputs 1 . I would like it to be any current value of $b .

What will be the smartest way in Perl to achieve a lazy score? I would like ${b} remain "unreplaced" until $a is needed.

+7
string perl lazy-evaluation
source share
6 answers

I'm more interested in knowing why you want to do this. You can use different approaches depending on what you really need to do.

You can wrap the code in coderef and only evaluate it when you need it:

 use strict; use warnings; my $b = '1'; my $a = sub { $b }; $b = '2'; print $a->(); 

A variation on this would be to use a named function as closure (this is probably the best approach in the wider context of your code code):

 my $b = '1'; sub print_b { print $b; } $b = '2'; print_b(); 

You can use the link to the source variable and dereference it as needed:

 my $b = '1'; my $a = \$b; $b = '2'; print $$a; 
+15
source share

Perl will interpolate the line when the code runs, and I don't know how to do it wrong, except for the formats (which are ugly IMOs). However, what you can do is change β€œwhen the code works” to something more convenient by wrapping the string in sub and calling it when you need the string interpolated ...

 $b = "1"; my $a = sub { "\$b is $b" }; $b = "2"; print &$a; 

Or you could do some eval magic, but it's a little more intrusive (you will need to manipulate the string a bit to reach it).

+4
source share

What you want is not a lazy assessment, but a late binding. To get it in Perl, you need to use eval .

 my $number = 3; my $val = ""; my $x = '$val="${number}"'; $number = 42; eval $x; print "val is now $val\n"; 

It should be borne in mind that eval usually inefficient and also methodologically brutal. You are almost certainly better off using the solution to one of the other answers.

+3
source share

As already mentioned, Perl will evaluate strings only as you wrote them, using eval to call the compiler at runtime. You can use links as mentioned in some other answers, but this changes the look of the code ( $$a vs $a ). However, this is Perl, there is a way to hide extended functionality behind a simple variable using tie .

 {package Lazy; sub TIESCALAR {bless \$_[1]} # store a reference to $b sub FETCH {${$_[0]}} # dereference $b sub STORE {${$_[0]} = $_[1]} # dereference $b and assign to it sub new {tie $_[1] => $_[0], $_[2]} # syntactic sugar } my $b = 1; Lazy->new( my $a => $b ); # '=>' or ',' but not '=' print "$a\n"; # prints 1 $b = 2; print "$a\n"; # prints 2 

You can find documentation for tie , but in a nutshell it allows you to define your own implementation of a variable (for scalars, arrays, hashes, or files). Thus, this code creates a new variable $a with an implementation that gets or sets the current value of $b (by storing the reference to $b internally). The new method is not strictly necessary (the constructor is actually TIESCALAR ), but is provided as syntactic sugar to avoid using tie directly in the calling code.

(which would be tie my $a, 'Lazy', $b; )

+3
source share

You want to pretend that $ a refers to what is evaluated when using $ a ... You can only do this if $ a is not really a scalar, it could be a function (like cHao's answer) or, in in this simple case, a reference to another variable

 my $b="1"; my $a= \$b; $b="2"; print $$a; 
+1
source share

I would like $ {b} to remain "unreplaced" until $ a is needed.

Then I would recommend excluding string interpolation, using sprintf instead, so that you "interpolate" if necessary.

Of course, on this basis, you could tie along with something fast (ish) and dirty:

 use strict; use warnings; package LazySprintf; # oh, yuck sub TIESCALAR { my $class = shift; bless \@_, $class; } sub FETCH { my $self = shift; sprintf $self->[0], @$self[1..$#$self]; } package main; my $var = "foo"; tie my $lazy, 'LazySprintf', '%s', $var; print "$lazy\n"; # prints "foo\n" $var = "bar"; print "$lazy\n"; # prints "bar\n"; 

Works with more exotic format specifiers. Ugh.

+1
source share

All Articles