考虑下面的Perl代码。的Perl,评估串懒洋洋地
#!/usr/bin/perl
use strict;
use warnings;
$b="1";
my $a="${b}";
$b="2";
print $a;
该脚本显然输出1
。我希望它是$b
的当前值。
什么是Perl中最聪明的方式来达到延迟计算也是这样吗?我希望${b}
保持“不更换”,直到需要$a
。
考虑下面的Perl代码。的Perl,评估串懒洋洋地
#!/usr/bin/perl
use strict;
use warnings;
$b="1";
my $a="${b}";
$b="2";
print $a;
该脚本显然输出1
。我希望它是$b
的当前值。
什么是Perl中最聪明的方式来达到延迟计算也是这样吗?我希望${b}
保持“不更换”,直到需要$a
。
我更感兴趣知道你为什么要这样做。根据你真正需要做什么,你可以使用各种方法。
你可以包裹在CODEREF代码,只评估它当你需要它:
use strict; use warnings;
my $b = '1';
my $a = sub { $b };
$b = '2';
print $a->();
这方面的一个变种是使用一个命名函数作为closure(这可能是最好的的方针,在您的调用代码大背景下):
my $b = '1';
sub print_b
{
print $b;
}
$b = '2';
print_b();
您可以使用原来的变量的引用,并取消对它的引用需要:
my $b = '1';
my $a = \$b;
$b = '2';
print $$a;
的代码运行时Perl会插一个字符串,我不知道的方式,使之不这样做,短格式(这是丑陋的IMO)。你可以做什么,不过,是改变“当代码运行”的东西更方便,在副包裹串并调用它,当你需要插入串...
$b = "1";
my $a = sub { "\$b is $b" };
$b = "2";
print &$a;
或者,你可以做一些eval的魔法,但它有点侵入性(你需要对字符串进行一些操作才能实现它)。
你想假装$ a是指当使用$ a时被评估的东西......如果$ a不是真正的标量,它可能是一个函数(如cHao的答案)或者,在这种简单的情况下,引用另一个变量
my $b="1";
my $a= \$b;
$b="2";
print $$a;
你想要的是不是懒惰的评价,但后期绑定。要使用Perl,你需要使用eval
。
my $number = 3;
my $val = "";
my $x = '$val="${number}"';
$number = 42;
eval $x;
print "val is now $val\n";
请注意,eval
通常是效率低下以及有条不紊的。使用来自其他答案之一的解决方案几乎肯定会更好。
正如其他人所说,Perl将仅作为您使用eval
调用在运行时编译器写他们评估的字符串。您可以使用引用在一些其他的答案中指出,但改变了代码的样子($$a
VS $a
)。但是,这是Perl,可以通过使用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
您可以查找的文档tie
,但简而言之,它允许你定义自己的实现变量(标量,数组,哈希,或文件句柄)。因此,此代码创建新变量$a
,其实现方式为获取或设置当前值$b
(通过在内部存储对$b
的引用)。 new
方法并不是严格需要的(构造函数实际上是TIESCALAR
),但作为语法糖提供,以避免直接在调用代码中使用tie
。
(这将是tie my $a, 'Lazy', $b;
)
我想$ {B}保持 “未置换” 直到需要$一个。
然后,我建议避开字符串插值,而不是使用sprintf
,以便在需要时“插入”。
当然,在此基础上,你可以tie
在一起的东西快速(ISH)和脏:
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";
厂采用较特殊的格式说明,太。呸。
完全真棒'yuck':-) – 2010-06-10 06:34:26
我建议不要使用'$ a'和'$ b'来举例这样的例子,因为这些都是perl特性,* not * lexically作用域(如你在'$前面省略'my' b'在你的例子中)。 – pilcrow 2010-06-10 06:13:27