Raku lambdas 的意外行为应该是相等的(我猜)
我正在学习 Raku 作为一个热情项目,我想实现一个简单 fizzbuzz,为什么如果我用尖头块编写 lambda 表达式,join
只会保留嗡嗡声?
my $iif =-> $x,$y,$z {if $x {$y} else {$z}}
my $modToString =-> $x,$y,$z {$iif($x%%$y,$z,'')}
my $FB =-> $x {join($modToString($x,3,'fizz'),$modToString($x,5,'buzz'))}
my $logic =-> $x {$iif($FB($x),$FB($x),$x)}
say map(-> $x {$logic($x)}, 1..100)
$modToString(1,3,'fizz')
>
$modToString(3,3,'fizz')
> fizz
$modToString(3,5,'buzz')
>
$modToString(5,5,'buzz')
> buzz
如果我将尖头块变量转换为占位符变量,Rakudo 会抛出错误:
my $iif = {if $^x {$^y} else {$^z}};
my $modToString = {$iif($^x%%$^y,$^z,'')};
my $FB = {join($modToString($^x,3,'fizz'),$modToString($^x,5,'buzz'))}
my $logic = {$iif($FB($^x),$FB($^x),$^x)}
say map(-> $x {$logic($x)}, 1..100)
Too many positionals passed; expected 1 argument but got 3
in block at <unknown file> line 1
in block at <unknown file> line 1
in block at <unknown file> line 1
in block at <unknown file> line 1
in block <unit> at <unknown file> line 1
如果我将括号放在连接参数周围,它只会输出数字:
my $iif =-> $x,$y,$z {if $x {$y} else {$z}}
my $modToString =-> $x,$y,$z {$iif($x%%$y,$z,'')}
my $FB =-> $x {join(<$modToString($x,3,'fizz'),$modToString($x,5,'buzz')>)}
my $logic =-> $x {$iif($FB($x),$FB($x),$x)}
say map(-> $x {$logic($x)}, 1..100)
为什么?
I'm learning Raku as a passion project and I wanted to implement a simple fizzbuzz, why is join
only retaining buzz if I write lambdas with pointy blocks?
my $iif =-> $x,$y,$z {if $x {$y} else {$z}}
my $modToString =-> $x,$y,$z {$iif($x%%$y,$z,'')}
my $FB =-> $x {join($modToString($x,3,'fizz'),$modToString($x,5,'buzz'))}
my $logic =-> $x {$iif($FB($x),$FB($x),$x)}
say map(-> $x {$logic($x)}, 1..100)
$modToString(1,3,'fizz')
>
$modToString(3,3,'fizz')
> fizz
$modToString(3,5,'buzz')
>
$modToString(5,5,'buzz')
> buzz
If I transform the pointy blocks variables into placeholder variables, Rakudo throws an error:
my $iif = {if $^x {$^y} else {$^z}};
my $modToString = {$iif($^x%%$^y,$^z,'')};
my $FB = {join($modToString($^x,3,'fizz'),$modToString($^x,5,'buzz'))}
my $logic = {$iif($FB($^x),$FB($^x),$^x)}
say map(-> $x {$logic($x)}, 1..100)
Too many positionals passed; expected 1 argument but got 3
in block at <unknown file> line 1
in block at <unknown file> line 1
in block at <unknown file> line 1
in block at <unknown file> line 1
in block <unit> at <unknown file> line 1
If I put the brackets around the join arguments it just outputs the numbers:
my $iif =-> $x,$y,$z {if $x {$y} else {$z}}
my $modToString =-> $x,$y,$z {$iif($x%%$y,$z,'')}
my $FB =-> $x {join(<$modToString($x,3,'fizz'),$modToString($x,5,'buzz')>)}
my $logic =-> $x {$iif($FB($x),$FB($x),$x)}
say map(-> $x {$logic($x)}, 1..100)
Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
因为 Raku 中的很多东西都是块,甚至是看起来不像的东西。特别是,这包括控制流程的“参数”,如
if
。我们实际上在这里写了两个块。一种是返回
2
的常量函数,另一种是返回3
的常量函数。现在,通常这对我们来说是透明的,并且 Raku 引擎足够智能,可以将这些编译掉。但他们还在那里。事实上,我们可以将它们明确化。以下的行为与上面的if
语句相同。然而,就您而言,这最终很重要。匿名参数(带有
^
twigil 的参数)绑定到最里面的块。所以你已经写了并且你打算让它等同于
但你实际写的是
所以你真的写了一个只有一个参数的函数并向它传递了三个参数,如错误消息所述。
作为一个广泛的规则,您通常可以假设任何时候您看到
{
,它要么开始一个散列文字,要么开始一个块。后者总是引入局部变量和参数可以存在的范围。在您的特定情况下,您可以使用三元
??!!
运算符(这与大多数其他语言(如 C++ 或 Java)中的?:
相同)此运算符不不会短路,也不会引入阻塞,因此它可以正常工作。
Because lots of things in Raku are blocks, even things that don't look like it. In particular, this includes the "argument" to control flow like
if
.We've actually written two blocks here. One is a constant function returning
2
and the other is a constant function returning3
. Now, usually, this is transparent to us and the Raku engine is smart enough to compile those away. But they're still there. In fact, we can make them explicit. The following behaves identically to the aboveif
statement.In your case, however, it ends up mattering. Anonymous arguments (the ones with the
^
twigil) bind to the innermost block. So you've writtenand you intended that it be equivalent to
but what you actually wrote was
So you've really written a function of one argument and passed it three arguments, as the error message states.
As a broad rule, you can generally assume that anytime you see a
{
, it either begins a hash literal or a block. And the latter always introduces a scope in which local variables and arguments can exist.In your particular case, you can use the ternary
??!!
operator (this is the same thing as?:
in most other languages like C++ or Java)This operator doesn't short-circuit and doesn't introduce blocks, so it'll work fine.
将OP的解决方案从问题迁移到答案。
Migrating OP's solution from the question to an answer.