2016-11-21 87 views
7

在Perl 6,I可以遍歷一個文字序列:如何將一個序列作爲參數傳遞給Perl 6?

.say for 0 ... 3; 

我可以綁定到一個標量和該迭代:

my $s := 0 ... 3; 
.say for $s; 

但我不能結合到一個標量,把它作爲一個參數,然後迭代的是:

my $t := 0 ... 3; 
show($t); 

sub show ($seq) { .say for $seq } 

子程序得到Seq類型的單個元件,但它不遍歷它。

0 
1 
2 
3 
0 
1 
2 
3 
(0 1 2 3) 

是否在準備參數的過程中迭代了所有內容?

回答

10

Scalar容器所保持的值爲自動迭代

雖然兩者$s$seqscalars(又名「變量」),$s直接綁定到一個序列值,而你的$seq綁定到一箇中間人Scalar(注意大寫S)「容器」,其中包含Seq。在使用for等功能時,標量容器中保存的值爲而不是


更詳細地:

my $s := 0 ... 3; 
.say for $s; 

由於my變量聲明使用用於初始化的直接結合操作者:=$s直接綁定到單個SEQ值0 ... 3

這意味着for語句看到單個Seq值,確定它執行Iterable角色並將其平滑(迭代)。

現在考慮這個:

my $s := 0 ... 3; 
my $container = $s; 
.say for $container; 

由於第二my聲明使用初始化賦值運算符=,新的變量$container首先必然然後「包含」任何被分配一個新的標容器。

與語言保持寬Slurpy Conventions(特別是:「一個標量容器內可迭代不計」),一個for語句不重複在一個標量容器內的值,所以.say for $container線只做一say

類似的情況適用於您的原始show例程,因爲可變參數聲明默認情況下是(語義)容器。

一個選項是一個is raw性狀而不是添加到$seq參數:

sub show ($seq is raw) { .say for $seq } 

這防止$seq通常的自動綁定到一個標量容器(這反過來將包含SEQ值)作爲其一部分致電show

另一種選擇是讓$seq使用前綴|被綁定到一個標量容器,但明確地變平(迭代)的$seq變量在show例程的主體:

sub show ($seq) { .say for |$seq } 
6

相反的is raw參數性狀通過raiph建議,你也可以使用一個印記少變量作爲參數,它不引入Scalar容器:

sub show (\seq) { .say for seq } 

(您也可以使用這種形式爲普通變量,如my \a = 5; say a;,但請注意,他們只是單賦值。)

這方面的一個變化是+形式,通過對原始參數,如果它是一個Iterable(如ListSeq),但是當非可迭代參數被傳遞它它促進將一個元件的List,使得函數體可以依靠總是得到一個Iterable

sub show (+seq) { .say for seq } 

(這是大多數內置列表處理例程,如grepzip使用)

當然,如果你喜歡使用$參數引入Scalar容器中,你可以「decontainerize」再次遍歷它,通過調用它的.list方法之前:

sub show ($seq) { .say for $seq.list } # explicit 

sub show ($seq) { .say for @$seq }  # short-hand syntax 

(更新:Eh,.list實際上將Seq轉換爲List,即在大Seq的情況下它將不具有存儲效率。使用|$seq就像你已經在你自己的答案中發現的那樣,沒有這個問題。)

+0

Thanks!但是,我正在考慮無限的懶序列。 :) –

相關問題