compiler-errors - "Two terms in a row"错误

标签 compiler-errors syntax-error raku

我正在尝试编写如下的紧凑行,该代码是从使用动态范围的特殊变量 $*IN 读取 STDIN 的脚本中提取的。你能建议如何正确地写这一行吗?

这个作品

for $*IN.lines() {
    last when "" ;
    say "VERBOSE \"$_ is the string\"";
    $i=$i+1;
}

不起作用
.say "VERBOSE \"$_ is the string\"" for $*IN.lines() last when "";

错误输出:
===SORRY!=== Error while compiling /usr/share/asterisk/agi-bin/agi-t1.p6
Two terms in a row
at /usr/share/asterisk/agi-bin/agi-t1.p6:5
------> .say⏏ "Verbose \"$_\"" for $*IN.lines() last
expecting any of:
  infix
  infix stopper
  statement end
  statement modifier
  statement modifier loop

最佳答案

错误消息的一般解释

===SORRY!=== Error while compiling ...
当您看到 SORRY! ,那么您就知道编译器正在与您讨论编译期间发生的问题,甚至在尝试运行您的代码之前。
Two terms in a row
这是编译器关于阻止它编译代码的原因的英文摘要。我们稍后会回到它。------>是编译器的说法,它被你写的东西弄糊涂了,它会在 ------> 之后显示你的一些代码。 . , Unicode 名称为 EJECT SYMBOL 的字符, 插入到代码的显示中。它插入的点应该有助于解释错误消息。
在这种情况下,它指向 .say 之间和 "VERBOSE..." .编译器认为这是连续的两个术语。
什么是术语?
考虑以下代码:
start-time + 42
sum(start-time, 42)
术语有点像 terms in mathematics .两个示例表达式都包含术语 start-time42 .整体表达start-time + 42也是一个术语。表达式 sum(start-time, 42)可能被称为 sum()术语或 sum(...)学期。
条款也有点像nouns or noun phrases in natural language . start-time42就像名词,因此是术语。 start-time + 42sum(...)就像名词短语,每个短语也是一个术语。
(顺便说一句,在与这个问题相关的意义上,术语与解析有时称为“术语”的“终端”无关。)
现在,如果您尝试编译本节开头的示例代码,您可能已经猜到会发生什么:
Two terms in a row across lines (missing semicolon or comma?)
第一行 ( start-time + 42 ) 是一个术语。 sum(start-time, 42)是另一个术语。它们之间除了线端之外什么都没有。 Raku 显然不喜欢连续的两个术语,而在它们之间没有不是术语的东西,并且空格和行尾不算数。
如何避免“连续两项”错误?
运算符如中缀 + , 后缀 () , 和中缀 ,我在上面的例子中使用的可以用于操作符位置(之前、之后、中间或周围,术语)来形成表达式。 (并且整个表达式本身就是如上所述的术语。)
关键字如 forlast , 用在关键字位置,也不是术语(除非你足够疯狂,将它们重新定义为术语,在这种情况下,你可能会得到你应得的奇怪的编译错误。:))但是,像运算符一样,它们必须放在正确的位置或编译器可能认为它们是术语。如果你写 last在错误的地方,编译器可能会认为 last是一个术语。
你的代码有问题
编译器考虑 .say (注意末尾的空格)是一个术语,相当于.say() .所以它会将你写的内容解释为 .say() "VERBOSE..."这是连续的两个术语。
(我建议你接受事实就是如此,但如果你想深入了解方法调用语法的细节以完全理解为什么 invocant.foo ( arrgh, arrgh, ... ) ; 也是“连续两个术语”,请参阅 my answer covering various syntaxes related to routine calls 。)
让我们通过更改 .say 来修复您的代码至 say (没有 . ):
say "VERBOSE \"$_ is the string\"" for $*IN.lines() last when "";
编译器返回另一个“连续两个术语”错误,但现在它指向 $*IN.lines()last .for关键字及其迭代参数必须位于语句的开头或语句的结尾。你最终使用了它们。
但这意味着 for 之后的内容是一个术语(它的迭代参数)。$*IN.lines()可以作为一个术语。
你甚至可以让它成为表达式的一部分,例如。 for flat $*IN.lines(), $*FOO.lines()循环遍历输入行和来自其他句柄的行。 ( flatfor 创建一个列表,通过展平两个单独的列表来循环,一个来自 $*IN.lines() ,另一个来自 $*FOO.lines() 。)
但是你没有建立表达式,你只是立即关注$*IN.lines()last .
因为没有 last中缀运算符和 last必须是语句中的第一个单词才能将其解释为关键字 last ,编译器转而解释 last作为一个术语——因此它看到“连续两个术语”。
您需要 last是一个语句关键字,它需要在 for 的上下文中环形。但是您已经在 for 的上下文中发表了声明。循环,即 say ...表达/术语。您需要一些括号或类似的东西来允许您编写多个语句。这是一种方法:
{ last when ""; say "VERBOSE \"$_ is the string\""; $i=$i+1 } for $*IN.lines();
现在您的代码有效。
最后的调整
我不妨做一些最后的调整:
( last when ''; say qq[VERBOSE "$_ is the string"]; $i++ ) for lines ;
  • 我是从 {...} 转过来的至 (...) .它不是更紧凑,但它表明当 for 时,您可以使用括号而不是大括号。写为语句修饰符(即在语句的末尾而不是在开头)。 {...}创建一个词法范围,而 (...)才不是;有时,其中之一正是您所需要的。
  • 您不需要 $*IN.因为有一个 lines sub 相当于 $*IN.lines() .
  • 我已经放弃了 ()之后 lines因为如果 lines 之后没有参数,则不需要它们(或 $*IN.lines )并且在语句结束之前。
  • 我用过 ''而不是 ""因为我认为如果不需要内插引号,使用非内插引号是一个好习惯。
  • 我用过 qq[...]因为这意味着您不必逃避 "在字符串中。
  • 我用过 $i++而不是 $i=$i+1因为它达到了同样的效果,而且我认为它读起来更好。
  • 关于compiler-errors - "Two terms in a row"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50775130/

    相关文章:

    xcode - 图像.xcassets : error: ERROR: Each TDDistiller instance can be distilled only one time

    compiler-errors - 为什么有些错误会保持沉默?

    powershell -and 运算符与测试路径语法错误

    sql - 如何使 SELECT NEXT VALUE 在 SQL Server 中工作?

    java - token 语法错误 "(", ;预期的

    operator-overloading - Raku 运算符重载

    java - XUGGLE 错误 : Exception in thread "main" java. lang.NoClassDefFoundError: org/slf4j/LoggerFactory

    java - 具有相同静态变量名称的静态导入

    Perl6 : How could I make all warnings fatal?

    raku - Perl 6 阻塞等待被杀死的 Proc::Async