【问题标题】:WhateverStar `&&` WhateverStar in Perl 6Perl 6中的WhateverStar`&&`WhateverStar
【发布时间】:2018-05-10 12:25:59
【问题描述】:

grep 中使用的* > 20 && * %% 5 似乎是错误的,是否等于带有 2 个参数的whateverCode lambda?正如SO上的解释@

> my @a = 1,12,15,20,25,30,35,37;

> @a.grep: * > 20 && * %% 5 # The result seems strange, expected (25 30 35)
(15 20 25 30 35)

> @a.grep: * %% 5 && * > 20
(25 30 35 37)

> @a.grep: { $_>20 && $_ %% 5 }
(25 30 35)

> @a.grep: all(* > 20, * %% 5)
(25 30 35)

> @a.grep: -> $a { all($a > 20, $a %% 5) }
(25 30 35)

> @a.grep: -> $a {$a > 20 && $a %% 5}
(25 30 35)

【问题讨论】:

  • 奇怪的是,如果你反转 && 的操作数,它会起作用:@a.grep: * %% 5 && * > 20
  • @Håkon Hægland 不,它似乎在&& 的右侧计算结果:* %% 5 && * > 20* > 20
  • @raiph 也许你是对的,这是一个错误
  • 再次删除。所以除了前两个之外,你所有的案例都是有道理的,对吧?在第 4 种情况下使用两个 * 是两个使用一个 *,因为 , 分隔表达式。所以你只使用了两个*,在前两种情况下,你会期望创建一个两个arg lambda。使用 occam 的剃刀,我注意到前两种情况似乎只是在做相当于忽略 && 左手的一个 arg lambda。另外,Brian 的猜测并不能解释您的第一个案例。
  • 引用我之前的评论:“所以你只使用了两个*,在前两种情况下,人们期望创建一个两个 arg lambda。”所以,我们的期望就是问题所在。请参阅您和我的回答,以了解与您的前两种情况类似的代码清楚地产生了一个 arg lambdas - 以及我对原因的回答。

标签: raku


【解决方案1】:

打高尔夫球

my &or  = * == 1 || * == 2 ;
my &and = * == 1 && * == 2 ;

say .signature, .(1), .(2)
  for &or, ∧

显示:

(;; $whatevercode_arg_1 is raw)TrueFalse
(;; $whatevercode_arg_4 is raw)FalseTrue

我仍然不知道发生了什么随着谜团的展开,我保留了我在这个答案中写的内容],但很明显,签名仅用于一个 arg,结果与 &and 的右手表达式和 &or 的左手表达式一致这意味着代码似乎没有,呃,留下了,呃,对的结果。调查仍在继续……(不,我不是重复者)。

谜团解开

因此,看起来逻辑操作(&&||andor 等)不执行 Whatever-currying。考虑到"not all operators and syntactic constructs curry * (or Whatever-stars) to WhateverCode",这很公平。考虑到它们的性质,甚至是合乎逻辑的。不过,它们可能应该被添加到该页面上的异常表中。

与此同时,== 等运算符 do Whatever curry。同样,考虑到"subexpressions may impose their own Whatever star rules",这很公平。

所以&or&and 转为...

啊哈!知道了。 * == 1* == 2 在编译时被评估并变成 WhateverCodes。作为WhateverCodes,它们只是一些代码。它们被定义。他们是True。 (这忽略了在运行时调用它们。)然后出现&& 并计算到右手WhateverCode。 (|| 将评估到它的左手 WhateverCode。)

因此我们看到的行为。

解决方案

根据@HåkonHægland 的提示,工作的代码因此是不依赖于逻辑操作Whatever-currying 的代码,即:

my @a = 1,12,15,20,25,30,35,37;

say @a.grep: { $_ > 20 && $_ %% 5 } # (25 30 35)

现在呢?

现在我们必须弄清楚要提出哪些文档编辑...

实际上,在我们这样做之前,请确认逻辑操作不应该是Whatever-curry...

为了开始滚动,我只是搜索了TimToady comments on #perl6 about "currying" 的搜索结果(#perl6-dev 上没有),寻找与我们这里的案例相关的结果。

首先,2017 年的一个可以说与任何文档编辑相关:

设计文档实际上尽量避免使用“currying”这个词......但很难让人们使用不同的词

接下来,2015 年的一篇关于 &&|| 等:

||&& 等是真正的控制流操作符,很快就变成了“如果”和“除非”……这些操作可以用 .assuming 进行咖喱,我假设

最后是 2010 年的一对似乎也可能很重要的夫妇(尽管可能有一个或多个不再适用?):

所有运算符都会自动识别WhateverCode,无论他们是否使用Whatever

我认为我们可以保留当前机制作为仍然希望在运行时进行 curry 的操作员的后备

【讨论】:

  • 关于* > 20 && * %% 5 的原始问题应该如何编写才能获得预期的输出(25 30 35)?还是不可能?
  • @HåkonHægland 鉴于逻辑操作不Whatever-curry,编写它而不依赖于:{ $_ > 20 && $_ %% 5 } 应该可以工作。是的,经过测试,有效。
  • 好的。感谢您的澄清!
【解决方案2】:
> my $d = * + * + * 
> $d.arity
3
> my $e = * == 1 || * == 2 || * == 3 
> $e.arity
1

正如doc 所说:

返回为了调用代码对象而必须传递的位置参数的最小数量。

所以我认为* == 1 || * == 2 || * == 3 中的所有三颗星都是一回事。

> my $e = * == 1 && * == 2 && * > 3 
> $e(1)
False
> $e(2)
False
> $e(3)
False
> $e(4)
True

【讨论】:

  • 是的。我的回答解释了原因。
  • 是的。 :) 事后看来是如此明显。到那时还真是莫名其妙。我写的那个“啊哈”字面意思是在我写那句话的时候发生的。 (我想在我写作时发生“字面意思”并不奇怪,但你知道我的意思。)
猜你喜欢
  • 1970-01-01
  • 2016-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多