如何动态创建捕获 (Raku)
How to create a Capture dynamically (Raku)
在下面的示例中,我尝试通过 "converting" 数组 (@a) 到 Capture 来动态创建 Capture。
考虑代码:
sub f (|c){
say '';
say ' List : ' ~ do {c.list.gist if c.list.elems > 0};
say ' Hash : ' ~ do {c.hash.gist if c.hash.elems > 0};
say '';
}
my $c1 = \(1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9);
my @a = 1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9;
my $c2 = \(|@a);
f(|$c1);
f(|@a);
f(|$c2);
结果是:
List : (1 (2 3) 4 5 6 7 8 9)
Hash : Map.new((t1 => test1, t2 => test2))
List : (1 (2 3) 4 5 t1 => test1 6 7 t2 => test2 8 9)
Hash :
List : (1 (2 3) 4 5 t1 => test1 6 7 t2 => test2 8 9)
Hash :
第一个 运行(使用 Capture $c1)是 运行ning 应该的,产生了预期的行为。
第二次和第三次尝试动态创建捕获失败(可能是因为在这些情况下子例程 f 的参数不是所需的捕获)。
我观察到合并到数组 @a 中的对被视为列表的成员,而不是我希望的命名参数。
我知道在传递给子例程 f 之前,数组中必须有 "flattening" 个对,但我想不出这样做的方法!
有人可以给我提示吗?
在 class List
中有方法 Capture
,它完全符合您的要求:
my $c = \(1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9);
my @a = 1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9;
my $c2 = @a.Capture;
f(|$c);
f(|$c2);
f(|@a);
sub f (|c){
say() ;
say ' List : ', c.List;
say ' Hash : ', c.Hash;
say();
}
您可以修改函数 f
的定义以直接使用列表 @a
。
my $c = \(1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9);
my @a = 1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9;
f($c);
f(@a);
sub f (Capture(Any) \c){
say() ;
say ' List : ', c.List;
say ' Hash : ', c.Hash;
say();
}
Capture(Any)
就是所谓的coercion type。它接受 Any
但强制 Capture
,即它(重复)调用方法 Capture
来获取它。
此外,通过Capture
您可以使用模式匹配。因此,函数 f
的最后定义可以更改为:
sub f ( (**@list, *%hash) ) {
#or even sub f ( (*@list, :t1($t),*%hash) ) {
say() ;
say ' List : ', @list;
# say ' test1 : ', $t;
say ' Hash : ', %hash;
say();
}
在下面的示例中,我尝试通过 "converting" 数组 (@a) 到 Capture 来动态创建 Capture。
考虑代码:
sub f (|c){
say '';
say ' List : ' ~ do {c.list.gist if c.list.elems > 0};
say ' Hash : ' ~ do {c.hash.gist if c.hash.elems > 0};
say '';
}
my $c1 = \(1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9);
my @a = 1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9;
my $c2 = \(|@a);
f(|$c1);
f(|@a);
f(|$c2);
结果是:
List : (1 (2 3) 4 5 6 7 8 9)
Hash : Map.new((t1 => test1, t2 => test2))
List : (1 (2 3) 4 5 t1 => test1 6 7 t2 => test2 8 9)
Hash :
List : (1 (2 3) 4 5 t1 => test1 6 7 t2 => test2 8 9)
Hash :
第一个 运行(使用 Capture $c1)是 运行ning 应该的,产生了预期的行为。 第二次和第三次尝试动态创建捕获失败(可能是因为在这些情况下子例程 f 的参数不是所需的捕获)。 我观察到合并到数组 @a 中的对被视为列表的成员,而不是我希望的命名参数。
我知道在传递给子例程 f 之前,数组中必须有 "flattening" 个对,但我想不出这样做的方法!
有人可以给我提示吗?
在 class List
中有方法 Capture
,它完全符合您的要求:
my $c = \(1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9);
my @a = 1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9;
my $c2 = @a.Capture;
f(|$c);
f(|$c2);
f(|@a);
sub f (|c){
say() ;
say ' List : ', c.List;
say ' Hash : ', c.Hash;
say();
}
您可以修改函数 f
的定义以直接使用列表 @a
。
my $c = \(1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9);
my @a = 1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9;
f($c);
f(@a);
sub f (Capture(Any) \c){
say() ;
say ' List : ', c.List;
say ' Hash : ', c.Hash;
say();
}
Capture(Any)
就是所谓的coercion type。它接受 Any
但强制 Capture
,即它(重复)调用方法 Capture
来获取它。
此外,通过Capture
您可以使用模式匹配。因此,函数 f
的最后定义可以更改为:
sub f ( (**@list, *%hash) ) {
#or even sub f ( (*@list, :t1($t),*%hash) ) {
say() ;
say ' List : ', @list;
# say ' test1 : ', $t;
say ' Hash : ', %hash;
say();
}