是否可以链接元运算符来计算 Raku 中两个列表的乘积和?
Is it possible to chain metaoperators to calculate the product-sum of two lists in Raku?
我正在学习 Raku,有些事情让我感到困惑。
为了计算两个列表(至少其中一个是有限的)的元素乘积之和,我希望能够写出类似
的东西
@a Z*[+] @b
但是没有给出预期的结果。
使用 [+] @a Z* @b
表单按预期工作
> my @a = 2...6;
[2 3 4 5 6]
> my @b = 5...1;
[5 4 3 2 1]
> @a Z @b;
((2 5) (3 4) (4 3) (5 2) (6 1))
> @a Z* @b;
(10 12 12 10 6)
> [+] @a Z* @b
50
但是当我将 Z*
和 [+]
链接在一起时它不喜欢它
> @a Z*[+] @b
(30)
> @a Z*+ @b
(10)
> @a +Z* @b
===SORRY!=== Error while compiling:
Undeclared name:
Z used at line 1
> @a +[Z*] @b
6
> @a [Z*]+ @b
(10)
> @a [Z*][+] @b
(30)
我想这里会发生一些优先级问题,但在 Raku 文档中找不到足够的示例。
我也发现了 >>*<<
无法解释的行为:
> [+] @a >>*<< @b
50
> @a [+][>>*<<] @b
125
> @a [>>*<<][+] @b
Lists on either side of non-dwimmy hyperop of infix:<*> are not of the same length while recursing
left: 5 elements, right: 1 elements
in block <unit> at <unknown file> line 1
问题
- 是否可以通过这种方式计算两个列表的乘积和?
- 不同链式变体之间发生了什么导致了
6
、(10)
、(30)
和 125
等结果?
Is it possible to evaluate the product-sum of two lists in this way?
是的。
让我们从链接开始:
可以编写从右到左链接的 Raku 代码,但我们将坚持从左到右。
从左到右的英语阅读你所谓的“产品总和”将是“sum of products 这些 列表 的元素”。所以我们想要左边的总和,接下来的产品,最后的列表。
有内建的sum
,没有内建的product
,所以我们需要处理后者。一种方法是将 [Z*]
写成 reduction(这意味着它必须出现在它减少的列表的左侧)。另一种是写一个新的product
函数。
综上所述,这里有一些我们可以写出“乘积总和”的方法:
say [+] [Z*] @a, @b; # 50 (closest to what it seems you want)
say sum [Z*] @a, @b; # 50 (`sum` is idiomatic)
say sum zip :with(&[*]), @a, @b; # 50 (some prefer `zip :with(&[*])` over `[Z*]`)
say sum product @a, @b; # 50 (requires a user defined `sub`)
sub product (|lists) { zip :with(&[*]), |lists }
如上操作意味着您可以使用任意数量的列表,而不仅仅是两个。
如果你真的想坚持使用中缀表示法,这将你限制在两个列表中,你可以对产品部分这样做:
say [+] @a Z* @b; # 50 (using infix sequential shallow zip metaop)
say [+] @a >>*<< @b; # 50 (using infix parallel nesting hyper metaop)
say sum @a Z* @b; # 50 (replacing `sum` with `[+]` reduction)
say sum @a >>*<< @b; # 50
What's happening across the different chained variants to cause results like 6
, (10)
, (30)
and 125
?
Raku 正确地执行了您的代码所表达的内容。
以下代码示例解释了所有 code/results @Zaid 共享的内容。您(任何 reader,而不仅仅是 @Zaid)可能需要做一些工作才能理解原因;如果您无法弄清楚这些示例如何解释 Zaid 的一个或多个结果,请发表评论,我很乐意在评论中进行解释 and/or 更新此答案并感谢您的 question/comment .
say my @a = 2...6; # [2 3 4 5 6]
say my @b = 5...1; # [5 4 3 2 1]
say [+] [5,4,3,2,1]; # 15
# Same as:
say sum @b; # 15
say 2 Z* 15; # (30)
# zip stops once shortest list exhausted, so same as:
say [2,3,4,5,6] Z* 15; # (30)
say +@b; # 5
# `+` coerces argument(s) to number, so short for:
say elems @b; # 5
# Same as:
say elems [5,4,3,2,1]; # 5
say 2 Z* 5; # (10)
#say +foo; # Error while compiling: Undeclared ... foo
# Same effect as:
#say foo; # Error while compiling: Undeclared ... foo
say [Z*] @b; # (120)
# Same as:
say 5 Z* 4 Z* 3 Z* 2 Z* 1; # (120)
say @a [Z*] 5; # (10)
# square brackets redundant, and
# zip stops once shortest list exhausted, so same as:
say 2 Z* 5; # (10)
say [+] @a >>*<< @b; # 50
say [>>*<<] @b; # 120
# hypers redundant if both args scalars, so same as:
say [*] [5,4,3,2,1]; # 120
# (5 * 4 * 3 * 2 * 1)
say @a [+] [>>*<<] @b; # 125
# square brackets round infix `+` redundant, so same as:
say @a + [>>*<<] @b; # 125
# hypers redundant if both args scalars, so same as:
say 5 + [*] @b; # 125 (5 + 120)
say @a [>>*<<][+] @b; # Same as:
say @a [>>*<<] [+] @b; #
say @a [>>*<<] sum @b; #
say @a >>*<< sum @b; #
#say @a >>*<< 15; # Lists on either side ... not of the same length
我正在学习 Raku,有些事情让我感到困惑。
为了计算两个列表(至少其中一个是有限的)的元素乘积之和,我希望能够写出类似
的东西@a Z*[+] @b
但是没有给出预期的结果。
使用 [+] @a Z* @b
表单按预期工作
> my @a = 2...6;
[2 3 4 5 6]
> my @b = 5...1;
[5 4 3 2 1]
> @a Z @b;
((2 5) (3 4) (4 3) (5 2) (6 1))
> @a Z* @b;
(10 12 12 10 6)
> [+] @a Z* @b
50
但是当我将 Z*
和 [+]
链接在一起时它不喜欢它
> @a Z*[+] @b
(30)
> @a Z*+ @b
(10)
> @a +Z* @b
===SORRY!=== Error while compiling:
Undeclared name:
Z used at line 1
> @a +[Z*] @b
6
> @a [Z*]+ @b
(10)
> @a [Z*][+] @b
(30)
我想这里会发生一些优先级问题,但在 Raku 文档中找不到足够的示例。
我也发现了 >>*<<
无法解释的行为:
> [+] @a >>*<< @b
50
> @a [+][>>*<<] @b
125
> @a [>>*<<][+] @b
Lists on either side of non-dwimmy hyperop of infix:<*> are not of the same length while recursing
left: 5 elements, right: 1 elements
in block <unit> at <unknown file> line 1
问题
- 是否可以通过这种方式计算两个列表的乘积和?
- 不同链式变体之间发生了什么导致了
6
、(10)
、(30)
和125
等结果?
Is it possible to evaluate the product-sum of two lists in this way?
是的。
让我们从链接开始:
可以编写从右到左链接的 Raku 代码,但我们将坚持从左到右。
从左到右的英语阅读你所谓的“产品总和”将是“sum of products 这些 列表 的元素”。所以我们想要左边的总和,接下来的产品,最后的列表。
有内建的sum
,没有内建的product
,所以我们需要处理后者。一种方法是将 [Z*]
写成 reduction(这意味着它必须出现在它减少的列表的左侧)。另一种是写一个新的product
函数。
综上所述,这里有一些我们可以写出“乘积总和”的方法:
say [+] [Z*] @a, @b; # 50 (closest to what it seems you want)
say sum [Z*] @a, @b; # 50 (`sum` is idiomatic)
say sum zip :with(&[*]), @a, @b; # 50 (some prefer `zip :with(&[*])` over `[Z*]`)
say sum product @a, @b; # 50 (requires a user defined `sub`)
sub product (|lists) { zip :with(&[*]), |lists }
如上操作意味着您可以使用任意数量的列表,而不仅仅是两个。
如果你真的想坚持使用中缀表示法,这将你限制在两个列表中,你可以对产品部分这样做:
say [+] @a Z* @b; # 50 (using infix sequential shallow zip metaop)
say [+] @a >>*<< @b; # 50 (using infix parallel nesting hyper metaop)
say sum @a Z* @b; # 50 (replacing `sum` with `[+]` reduction)
say sum @a >>*<< @b; # 50
What's happening across the different chained variants to cause results like
6
,(10)
,(30)
and125
?
Raku 正确地执行了您的代码所表达的内容。
以下代码示例解释了所有 code/results @Zaid 共享的内容。您(任何 reader,而不仅仅是 @Zaid)可能需要做一些工作才能理解原因;如果您无法弄清楚这些示例如何解释 Zaid 的一个或多个结果,请发表评论,我很乐意在评论中进行解释 and/or 更新此答案并感谢您的 question/comment .
say my @a = 2...6; # [2 3 4 5 6]
say my @b = 5...1; # [5 4 3 2 1]
say [+] [5,4,3,2,1]; # 15
# Same as:
say sum @b; # 15
say 2 Z* 15; # (30)
# zip stops once shortest list exhausted, so same as:
say [2,3,4,5,6] Z* 15; # (30)
say +@b; # 5
# `+` coerces argument(s) to number, so short for:
say elems @b; # 5
# Same as:
say elems [5,4,3,2,1]; # 5
say 2 Z* 5; # (10)
#say +foo; # Error while compiling: Undeclared ... foo
# Same effect as:
#say foo; # Error while compiling: Undeclared ... foo
say [Z*] @b; # (120)
# Same as:
say 5 Z* 4 Z* 3 Z* 2 Z* 1; # (120)
say @a [Z*] 5; # (10)
# square brackets redundant, and
# zip stops once shortest list exhausted, so same as:
say 2 Z* 5; # (10)
say [+] @a >>*<< @b; # 50
say [>>*<<] @b; # 120
# hypers redundant if both args scalars, so same as:
say [*] [5,4,3,2,1]; # 120
# (5 * 4 * 3 * 2 * 1)
say @a [+] [>>*<<] @b; # 125
# square brackets round infix `+` redundant, so same as:
say @a + [>>*<<] @b; # 125
# hypers redundant if both args scalars, so same as:
say 5 + [*] @b; # 125 (5 + 120)
say @a [>>*<<][+] @b; # Same as:
say @a [>>*<<] [+] @b; #
say @a [>>*<<] sum @b; #
say @a >>*<< sum @b; #
#say @a >>*<< 15; # Lists on either side ... not of the same length