say "1 10".split(" ")
返回 (1,10)
当我将这些1和10
作为参数传递给序列运算符[...]
时
say [...] "1 10".split(" ")
当使用split函数时,返回值为字符串,因此只返回了(1)而不是应该返回的(1 2 3 4 5 6 7 8 9 10)。如何解决这个问题呢?
谢谢。
say "1 10".split(" ")
返回 (1,10)
当我将这些1和10
作为参数传递给序列运算符[...]
时
say [...] "1 10".split(" ")
当使用split函数时,返回值为字符串,因此只返回了(1)而不是应该返回的(1 2 3 4 5 6 7 8 9 10)。如何解决这个问题呢?
谢谢。
如果您想要数字行为,则将其强制转换为数字:
say [...] +<< "1 10".split(" "); # (1 2 3 4 5 6 7 8 9 10)
这里使用了 <<
超运算符,将数值强制转换(前缀 +
)应用于 split
生成的序列中的每个元素。
关于以 字符串 为端点的序列和范围行为:
在 为什么 Perl 6 中的序列 'A' … 'AA'
只有一个元素? 中所描述的也适用于您指定的序列,即 "1"..."10"
。
开放的 Rakudo 问题 具有字符串端点且没有显式生成器的序列运算符会产生奇怪/未记录的结果。
在 为什么我的某些范围是疯狂的? 中讨论过类似的问题。
你写的代码等价于:
put gist "1"..."10";
(say
相当于 put gist
。)
"1"..."10"
的 gist
是 (1)
。
那是因为 List.new("1")
的 gist
就像 List.new("a")
的 gist
一样,都是 (a)
。
"1"..."10"
求值为 List.new("1")
。
为什么呢?我还不确定,但我正在探索可用的信息。
我们从文档开始。中缀操作符 ...
的文档说:
默认生成器是
*.succ
或*.pred
,具体取决于端点的比较结果
好的:
say "1" cmp "10"; # Less
这可能意味着该序列开始调用*.succ
。
然后:
say "1".succ; # 2
并且:
say "2" cmp "10"; # More
似乎这导致序列在“1”后立即终止,而没有包括“2”并继续。
我正在继续搜索错误队列并检查@wamba ++在其回答中链接到上面链接的SO“为什么Perl 6序列' A'… 'AA'只有一个元素?”周围的代码。
通常情况下,raiph给出了正确的答案,但是我认为他忽略了为什么它确实不起作用的原因。
主要原因是[]
是一个reduce运算符,除非作为副作用,否则它不会将括号内的内容视为中缀运算符。例如,以下代码可以正常工作:
say [+] <4 8>.words; # OUTPUT: «12»
只有因为有两个组件,且对它们应用了 []
的 reduce,才会产生相同的效果。对于 ...
也是如此。
say [...] <4 8>.words; # OUTPUT: «(4 5 6 7 8)»
然而,这不是您要寻找的。您有两个操作数,一个单一运算符,您想调用运算符本身。当然,您可以通过使用其完全限定名称来实现。
say infix:<...>( | <3 5>.words ); # OUTPUT: «(3 4 5)»
当然,只要您将参数(使用|)压成中缀操作符的签名匹配即可。
像往常一样,TIMTOWTDI。所以请按照最适合您的方式进行操作。
say infix:<...>( | <1 10>.words ); # OUTPUT: «(1)»
演示了问题仍然存在于您对语法的改写中。这与我链接到的'A' ... 'AA'
相同。但是,我的答案到目前为止有点匆忙和神秘。我计划在接下来的一天左右改进它,一旦我感觉已经收集了相关的错误报告、问题、IRC和设计文档讨论(特别是由Larry)以及Rakudo代码行,并且可以将其提炼出来,尽可能清晰地解释它。 - raiph
say [...] "1 10".split(" ").Seq
不行。它只返回(1)
,而期望的是返回(1 2 3 4 5 6 7 8 9 10)
。 - Terry"1 10".split(" ")
返回一个序列 -- 我使用(1,10).Seq
来使其等效。至于第三个数字放在哪里:这不像我建议的那样工作,请忽略。 - ugexe…
或...
),但那不是Range
操作符。中缀...
是序列操作符。它在左侧接受一个或多个初始值以及可选的生成器,右侧是一个智能匹配的结束值,并构造出一个Seq
。此外,还有一个中缀2点范围操作符,它构造出一个Range
。请参考:序列操作符和范围操作符。 - raiph…
,它对结果没有影响,即我仍然需要在目标序列(1 2 3 4 5 6 7 8 9 10)
中间加上 +<< hyperop 才能得到。 - Terry