考慮下面的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