使用 Raku 的 Code.assuming 方法和使用匿名 Block 或 Sub 有什么区别?

cod*_*ons 6 currying rakudo raku

乐文档说Code.assuming

返回一个实现与原始行为相同的行为的 Callable,但传递给 .assuming 的值已经绑定到相应的参数。

.assuming在调用内部函数的匿名块(或子)中使用和包装代码之间有什么区别?

例如,在下面的代码中,&surname-public(文档提供的示例.assuming)和&surname-block;之间的区别是什么?


sub longer-names ( $first, $middle, $last, $suffix ) {
    say "Name is $first $middle $last $suffix";
}

my &surname-public = &longer-names.assuming( *, *, 'Public', * );
my &surname-block  = -> $a,$b,$c { longer-names($a, $b, 'Public', $c) }

surname-public( 'Joe', 'Q.', 'Jr.');  # OUTPUT: «Name is Joe Q. Public Jr.»
surname-block(  'Joe', 'Q.', 'Jr.');  # OUTPUT: «Name is Joe Q. Public Jr.»
Run Code Online (Sandbox Code Playgroud)

我看到这.assuming节省了一些长度,并且在某些情况下可能会更清晰一些。但我强烈怀疑我错过了其他一些差异。

Bra*_*ert 5

真的没有什么区别。

虽然要实现的代码.assuming()将近 300 行,但重要的一点只有大约 10 行代码。

    $f = EVAL sprintf(
        '{ my $res = (my proto __PRIMED_ANON (%s) { {*} });
           my multi __PRIMED_ANON (|%s(%s)) {
               my %%chash := %s.hash;
               $self(%s%s |{ %%ahash, %%chash });
           };
           $res }()',
        $primed_sig, $capwrap, $primed_sig, $capwrap,
        (flat @clist).join(", "),
        (@clist ?? ',' !! '')
    );
Run Code Online (Sandbox Code Playgroud)

其余代码.assuming主要是关于从签名中提取信息。


让我们把你的代码插入到那个sprintf.
(不完全相同,但对于我们的目的来说已经足够接近了。)

{
  my $res = (
    #  $primed_sig          v----------------------v
    my proto __PRIMED_ANON ($first, $middle, $suffix) { {*} }
  );

  # $capwrap               vv
  # $primed_sig                v----------------------v
  my multi __PRIMED_ANON (|__ ($first, $middle, $suffix)) {
    # $capwrap   vv
    my %chash := __.hash;

    #     v---------------------------v  @clist
    $self(__[0], __[1], 'Public', __[2], |{ %ahash, %chash });
  };

  # return the proto
  $res
}()
Run Code Online (Sandbox Code Playgroud)

如果我们简化它,并根据您的代码定制它

my &surname-public = {
  my $res = (
    my proto __PRIMED_ANON ($first, $middle, $suffix) { {*} }
  );

  my multi __PRIMED_ANON ( $first, $middle, $suffix ) {
    longer-names( $first, $middle, 'Public', $suffix )
  };

  $res
}()
Run Code Online (Sandbox Code Playgroud)

我们可以通过使用一个尖块来进一步简化它。

my &surname-public = -> $first, $middle, $suffix {
  longer-names( $first, $middle, 'Public', $suffix )
};
Run Code Online (Sandbox Code Playgroud)

也只需使用单字母参数名称。

my &surname-public = -> $a,$b,$c { longer-names($a, $b, 'Public', $c) }
Run Code Online (Sandbox Code Playgroud)

就像我说的,真的没有区别。


将来,使用.assuming(). 在它被重写以使用 RakuAST 之后。