简体   繁体   English

如何动态创建捕获 (Raku)

[英]How to create a Capture dynamically (Raku)

In the following example I try to create a Capture dynamically by "converting" an array (@a) to a Capture.在以下示例中,我尝试通过将数组 (@a)“转换”为 Capture 来动态创建 Capture。

Consider the code:考虑代码:

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);

The result is:结果是:

  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 : 

The first run (with Capture $c1) is running as it should, producing the desired behaviour.第一次运行(使用 Capture $c1)按原样运行,产生所需的行为。 The second and third attempts, to create a Capture dynamically, are failing (probably because the argument of the subroutine f in those cases is NOT the desired Capture).动态创建 Capture 的第二次和第三次尝试失败(可能是因为在这些情况下子例程 f 的参数不是所需的 Capture)。 I observe that the pairs incorporated into array @a, are taken to be members of a list and NOT named parameters as I wanted them to be.我观察到合并到数组@a 中的对被视为列表的成员,而不是我想要的命名参数。

I know that there must be, sort of speak, a "flattening" of the pairs in the array going on, before passing to subroutine f, but i can NOT figure out the way to do that!我知道,在传递给子例程 f 之前,必须有,可以说,数组中的对“展平”,但我不知道如何做到这一点!

Can anyone give me a hint?谁能给我一个提示?

In the class List there is the method Capture , which works exactly how you want:在类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();
}

You could modify the definition of the function f to work directly with the list @a .您可以修改函数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) is so-called coercion type . Capture(Any)是所谓的强制类型 It accepts Any but coerces Capture , ie it (repeatedly) calls method Capture to get it.它接受Any但强制Capture ,即它(反复)调用方法Capture来获取它。

In addition, by Capture you can use pattern matching.此外,通过Capture您可以使用模式匹配。 Thus last definition of the function f could be changed to:因此,函数f最后定义可以更改为:

sub f ( (**@list, *%hash) ) {
#or even sub f ( (*@list, :t1($t),*%hash) ) {
    say() ;
    say '  List : ', @list;
    # say ' test1 : ', $t;
    say '  Hash : ', %hash;
    say();
}  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM