如何解决使用 Raku 的 Code.assuming 方法和使用匿名 Block 或 Sub 有什么区别?
那个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,$c) }
surname-public( 'Joe','Q.','Jr.'); # OUTPUT: «Name is Joe Q. Public Jr.»
surname-block( 'Joe','Jr.'); # OUTPUT: «Name is Joe Q. Public Jr.»
我看到 .assuming
节省了一些长度,并且在某些情况下可能会更清晰一些。但我强烈怀疑我遗漏了其他一些差异。
解决方法
真的没有区别。
虽然实现 .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,(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,$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,$suffix) { {*} }
);
my multi __PRIMED_ANON ( $first,$suffix ) {
longer-names( $first,$suffix )
};
$res
}()
我们可以通过使用一个尖块来进一步简化它。
my &surname-public = -> $first,$suffix {
longer-names( $first,$suffix )
};
也可以使用单字母参数名称。
my &surname-public = -> $a,$b,$c { longer-names($a,$c) }
就像我说的,真的没有区别。
在未来,使用.assuming()
可能更有利。重写后使用 RakuAST。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。