2011-01-12 19 views
17

Tanıdık olmayan bir programlama dilinde öğrenmeye çalıştığım ilk şeylerden biri, kapakların nasıl ele alınacağıdır. Semantikleri genellikle dilin kapsamları nasıl ele aldığına ve diğer zorlu bitlere nasıl işlediğiyle iç içe geçmiştir, bu yüzden onları anlamak, dilin diğer yönlerini ortaya çıkarır. Ayrıca, kapaklar gerçekten güçlü bir yapıdır ve çoğu zaman yazmam gereken boiler plakasının miktarını azaltır. Bu yüzden perl kapanışları ile karıştırmasını ve biraz Yakaladım tökezledi:

my @closures; 
foreach (1..3) { 
    # create some closures 
    push @closures, sub { say "I will remember $_"; }; 
} 
foreach (@closures) { 
    # call the closures to see what they remember 
    # the result is not obvious 
    &{$_}(); 
} 

ben

I will remember 1 
I will remember 2 
I will remember 3 

görmeyi bekliyordum ama bunun yerine I will remember CODE(0x986c1f0) var yukarıdaki kodu yazdığımda. Yukarıdaki deney, $_'un çok bağlamsal bağımlı olduğunu ve bir kapanışta göründüğü takdirde kapağın yaratıldığı noktada değerinin sabitlenmediğini ortaya çıkarmıştır. Daha çok bir referans gibi davranır. Perl'de kapanışlar yaratırken başka hangi tuhaflıkların farkında olmalıyım?

cevap

25

Kapanışlar yalnızca sözcüksel değişkenlerin üzerine kapanır; $_ normalde küresel bir değişkendir. 5.10 ve daha yukarısında, belirli bir kapsamda sözcüksel olması için my $_; yazabilirsiniz (ancak 5.18'de bu geriye dönük olarak deneysel ve değişime açık olduğu beyan edilmiştir, bu yüzden başka bir değişken adı kullanmak daha iyidir).

use strict; 
use warnings; 
use 5.010; 
my @closures; 
foreach my $_ (1..3) { 
    # create some closures 
    push @closures, sub { say "I will remember $_"; }; 
} 
foreach (@closures) { 
    # call the closures to see what they remember 
    # the result is not obvious 
    &{$_}(); 
} 
+2

Ancak bu, $ num'i foreach işlevinin kullanılması ile hemen hemen aynıdır .... – davidk01

+1

Yani, sadece sözcüksel değişkenleri kapatırlarsa diğer değişkenlere ne olur? Kapatma, arama sitesi sırasında kullanılabilir olan değeri "$ _" için olduğu gibi kullanıyor mu? – davidk01

+1

@ davidk01: global değişkenlere izin veren başka herhangi bir programlama dilinde olduğu gibi, kapanışlar normalde bu değişkeni gerçekten kapatır. Sadece bunun global olduğunu ve diğer kodun değerini başka bir şeye koyduğunda (anonim bir alt tarafından çağrıldığında) değişebileceğini unutmuşsunuzdur. – slebetman

3

$ _ global değişkendir ve kapatılmasıyla kullanılmamalıdır:

Bu beklenen çıktı üretir. Bunu kullanmadan önce, bunu bewlow olarak gösterildiği gibi sözcüksel olarak kapsam dışı bir değişkene atayın. Bu beklenen o/p üretecektir.

#!/usr/bin/perl -w 

use strict; 
my @closures; 


foreach (1..3) { 
    my $var = $_; 
    push @closures, sub { print "I will remember $var"; }; 
} 

foreach (@closures) { 
    $_->(); 
    print "\n"; 
}