Capture
是一个容器,用于将参数传递给代码对象。Capture 是 Signature
的另一面。因此,Capture 是调用者定义的参数,而 Signature 是被调用者定义的参数。例如,当您调用 print $a, $b
时,$a, $b
部分是一个 Capture。
Capture 包含一个类似列表的部分,用于存放位置参数,以及一个类似哈希的部分,用于存放命名参数,因此表现为 Positional
和 Associative
,尽管它实际上并没有混合这些角色。与任何其他数据结构一样,可以创建、存储和稍后使用独立的 Capture。
可以通过在术语前加上反斜杠 \
来创建文字 Capture
。通常,此术语将是术语的 List
,从中将 Pair
文字的 key => value
和 :key<value>
形式放入命名部分,所有其他术语将放入位置部分(包括 'key' => value
形式的 Pair
)。
my = \(42); # Capture with one positional argmy = \(1, 2, verbose => True); # Capture with two positional args and one named argmy = \(1, 2, :verbose(True)); # same as beforemy = \(1, 2, 'verbose' => True); # Capture with three positional args
重申一下,Capture 中的命名参数必须使用以下两种方式之一创建
使用一个未加引号的键来命名一个参数,后跟
=>
,后跟参数。例如,as => by => {1/$_}
。使用以参数命名的 冒号对 文字。例如,
:into(my %leap-years)
。
例如
sub greet(:, :)my = \(name => 'Mugen', age => 19); # OKmy = \(:name('Jin'), :age(20)); # OKmy = \('name' => 'Fuu', 'age' => 15); # Not OK, keys are quoted.
对于接受两个命名参数 name
和 age
的 greet
子例程,Capture $d
和 $e
将正常工作,而 Capture $f
将抛出 Too many positionals passed...
错误。这是因为 'age' => 20
不是命名参数(如上面提到的创建命名参数的两种方式),而是位置参数,而 greet
不期望有位置参数。在 Capture 的上下文中,带引号的键不会创建命名参数。任何 'key' => value
都只是另一个位置参数,因此在使用命名参数创建 Capture 时要小心。
创建 Capture 后,您可以在子例程调用中使用它,方法是在它前面加上一个竖线 |
,它将如同 Capture 中的值直接作为参数传递给子例程 — 命名参数将作为命名参数传递,位置参数将作为位置参数传递。您可以根据需要多次重复使用 Capture,甚至可以与不同的子例程一起使用。
say greet |; # OUTPUT: «Mugen, 19»say greet |; # OUTPUT: «Jin, 20»
my = \(4, 2, 3, -2);say reverse |; # OUTPUT: «(-2 3 2 4)»say sort 5, |; # OUTPUT: «(-2 2 3 4 5)»say unique |, as => ; # OUTPUT: «(4 2 3)»say unique |, :as(); # OUTPUT: «(4 2 3)»my = \(1, 7, 3, by => );say min |; # OUTPUT: «7», same as min 1, 7, 3, by => {1/$_}say max |; # OUTPUT: «1», same as max 1, 7, 3, by => {1/$_}
在 Signature
中,可以通过在 无 sigil 参数 前加上竖线 |
来创建 Capture
。这会将参数列表的其余部分打包到该 capture 参数 中。
sub f(, |c)f 1, 2, 3, a => 4, :b(5);# OUTPUT:# 1# \(2, 3, :a(4), :b(5))# Capture# (2 3)# Map.new((a => 4, b => 5))
请注意,Capture
仍然是 List
,因为它们可能包含容器,而不仅仅是字面值
my = 1;my = \(4, 2, , 3);say min |; # OUTPUT: «1»= -5;say min |; # OUTPUT: «-5»
方法§
方法列表§
method list(Capture:)
返回 Capture
的位置部分。
my Capture = \(2, 3, 5, apples => (red => 2));say .list; # OUTPUT: «(2 3 5)»
方法哈希§
method hash(Capture:)
返回 Capture
的命名/哈希部分。
my Capture = \(2, 3, 5, apples => (red => 2));say .hash; # OUTPUT: «Map.new((:apples(:red(2))))»
方法元素§
method elems(Capture: --> Int)
返回 Capture
中的位置元素数。
my Capture = \(2, 3, 5, apples => (red => 2));say .elems; # OUTPUT: «3»
方法键§
multi method keys(Capture: --> Seq)
返回 Seq
,其中包含所有位置键,后跟所有命名键。对于位置参数,键是从零开始的相应参数序数位置。
my = \(2, 3, 5, apples => (red => 2));say .keys; # OUTPUT: «(0 1 2 apples)»
方法值§
multi method values(Capture: --> Seq)
返回 Seq
,其中包含所有位置值,后跟所有命名参数值。
my = \(2, 3, 5, apples => (red => 2));say .values; # OUTPUT: «(2 3 5 red => 2)»
方法键值§
multi method kv(Capture: --> Seq)
返回 Seq
,其中包含交替的 键 和 值。如果存在,位置键和值先出现,然后是命名键和值。
my = \(2, 3, apples => (red => 2));say .kv; # OUTPUT: «(0 2 1 3 apples red => 2)»
方法对§
multi method pairs(Capture: --> Seq)
将所有参数(位置参数后跟命名参数)作为 Seq
的 Pair
返回。位置参数的键是其各自的序数值(从零开始),而命名参数的键是其名称。
my Capture = \(2, 3, apples => (red => 2));say .pairs; # OUTPUT: «(0 => 2 1 => 3 apples => red => 2)»
方法反对§
multi method antipairs(Capture: --> Seq)
将所有参数(位置参数后跟命名参数)作为 Seq
的 Pair
返回,其中键和值已交换,即值变为键,键变为值。此行为与 <pairs|#method_pairs> 方法相反。
my = \(2, 3, apples => (red => 2));say .antipairs; # OUTPUT: «(2 => 0 3 => 1 (red => 2) => apples)»
方法布尔§
method Bool(Capture: --> Bool)
如果 Capture
至少包含一个命名参数或一个位置参数,则返回 True
。
say \(1,2,3, apples => 2).Bool; # OUTPUT: «True»say \().Bool; # OUTPUT: «False»
方法捕获§
method Capture(Capture: --> Capture)
返回自身,即调用者。
say \(1,2,3, apples => 2).Capture; # OUTPUT: «\(1, 2, 3, :apples(2))»
方法数字§
method Numeric(Capture: --> Int)
返回 Capture
中的位置元素数。
say \(1,2,3, apples => 2).Numeric; # OUTPUT: «3»