使用 Raku 的 Code.assuming 方法和使用匿名 Block 或 Sub 有什么区别?
What is the difference between using Raku's Code.assuming method and using an anonymous Block or Sub?
Code.assuming
的Raku docs say
Returns a Callable that implements the same behavior as the original, but has the values passed to .assuming already bound to the corresponding parameters.
使用 .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.»
我看到 .assuming
节省了一些篇幅,并且在某些情况下可以更清楚一些。但我强烈怀疑我遗漏了一些其他差异。
确实没有区别。
虽然实现 .assuming()
的代码将近 300 行,但重要的一点只有大约十行代码。
$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 ?? ',' !! '')
);
.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
}()
如果我们简化它,并根据您的代码对其进行调整
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
}()
我们可以使用尖块进一步简化它。
my &surname-public = -> $first, $middle, $suffix {
longer-names( $first, $middle, 'Public', $suffix )
};
也可以只使用单字母参数名称。
my &surname-public = -> $a,$b,$c { longer-names($a, $b, 'Public', $c) }
就像我说的,真的没有区别。
以后使用.assuming()
可能更有好处。重写后使用 RakuAST。
Code.assuming
Returns a Callable that implements the same behavior as the original, but has the values passed to .assuming already bound to the corresponding parameters.
使用 .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.»
我看到 .assuming
节省了一些篇幅,并且在某些情况下可以更清楚一些。但我强烈怀疑我遗漏了一些其他差异。
确实没有区别。
虽然实现 .assuming()
的代码将近 300 行,但重要的一点只有大约十行代码。
$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 ?? ',' !! '')
);
.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
}()
如果我们简化它,并根据您的代码对其进行调整
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
}()
我们可以使用尖块进一步简化它。
my &surname-public = -> $first, $middle, $suffix {
longer-names( $first, $middle, 'Public', $suffix )
};
也可以只使用单字母参数名称。
my &surname-public = -> $a,$b,$c { longer-names($a, $b, 'Public', $c) }
就像我说的,真的没有区别。
以后使用.assuming()
可能更有好处。重写后使用 RakuAST。