如何修复有关结束关键字的Ruby语法错误?

How can I fix this Ruby syntax error concerning the end keyword?

提问人:readyready15728 提问时间:10/12/2019 更新时间:10/12/2019 访问量:521

问:

这是来自Exercism的一个问题。到目前为止,将每个解决方案都变成类方法似乎是一种奇怪的处理方式,但这不是我的想法。无论如何,这是代码:

class ResistorColorDuo
  @@colors = %w(
    black
    brown
    red
    orange
    yellow
    green
    blue
    violet
    grey
    white)

  def self.value(array)
    @@colors.index array[0] * 10 + @@colors.index array[1]
  end
end

错误消息:

Traceback (most recent call last):
    1: from resistor_color_duo_test.rb:2:in `<main>'
resistor_color_duo_test.rb:2:in `require_relative': /home/muhammad/exercism/ruby/resistor-color-duo/resistor_color_duo.rb:15: syntax error, unexpected tIDENTIFIER, expecting keyword_end (SyntaxError)
...0]) * 10 + @@colors.index array[1]

我看不出问题,因为关键字都正确平衡了。我应该如何解决这个问题?end

Ruby 编译器错误 语法错误

评论

4赞 dinjas 10/12/2019
您可能希望使用括号来确保按预期计算代码。例如。我想你想要这样的东西:@@colors.index(array[0]) * 10 + @@colors.index(array[1])
0赞 readyready15728 10/12/2019
我的印象是,在这种情况下,括号是可选的。来自 Python(以及 JS 和我曾经使用过的几乎所有其他东西)的奇怪怪癖。但这确实解决了问题。把它作为答案发布,我会接受它。
1赞 Cary Swoveland 10/12/2019
除了@dinjas的评论之外,当您更改为 时,它会编译,但除此之外,我不确定您将括号可视化在哪里。括号,即使可能不需要,也可以使代码更具可读性,并避免这样的错误。@@colors.index array[1]@@colors.index(array[1])
0赞 3limin4t0r 10/12/2019
@readyready15728括号是可选的,但出于优先原因,您不希望在大多数时候将它们省略。如果语句编译时不带括号,它将按照以下方式执行: 如果你不传递任何参数,或者你有一条干净的行,比如@@colors.index((array[0] * 10) + @@colors.index(array[1]))if array.include? element
1赞 BobRodes 10/12/2019
@dinjas我相信它是说它期望行的其余部分是第一个方法的参数,之后它期望关键字,但它得到了另一个带有空格参数的方法调用。如果将参数括号括在第二种方法上,则错误将消失。关于a是什么的文档并不多,但是当省略引号或paren或其他东西时,通常会出现“意外的tIDENTIFIER”错误。这并不意味着 OP 遗漏了一个 ,而是它正在寻找并遇到了其他东西。indexendindexindextIDENTIFIERendend

答:

2赞 Viktor 10/12/2019 #1

评论部分@dinjas答案的补充

如果有两个数组:

colors = [1,10]
array = [1]

并执行示例中所示的操作:

colors.index array[0] * 10

您将获得数组的第二个元素的索引,即 .这是因为 Ruby 将首先计算(即 ),然后检查数组中相等的第一个元素的索引。#=> 1colors10array[0] * 101 * 10 = 1010colors

但是,如果添加括号并执行此操作:

 colors.index(array[0]) * 10

你会得到,因为数组中等于 () 的第一个元素的索引是 和 。#=> 01array[0] = 1colors00 * 10 = 0

几天前也有一个类似的问题,你可能想在这里看看。

4赞 BobRodes 10/12/2019 #2

我的印象是,在这种情况下,括号是可选的。

是的,也不是。括号确实是可选的,但这并不意味着不使用它们不会改变代码的行为,只是不会出现语法错误。

如果 Ruby 在方法后面遇到空格,它会将该行的其余部分解析为其参数。因此,如果行上没有任何不属于方法参数的内容,则括号是可选的。如果这样做,则必须将行的哪一部分括在括号中来指定构成参数列表的部分。

下面是一个需要注意的相关潜在问题。请考虑以下行,它们仅相差一个空格:

f(3+2)+1
f (3+2)+1

其中第一个传递给函数并添加到结果中。第二个传递给函数 。出于同样的原因:如果 Ruby 在方法调用后立即遇到空格,则该行的其余部分将被解析为参数列表。5f16f

我从Matz的书中借用了这个例子,他在书中雄辩地称之为“有害的空白依赖”。您必须小心方法调用行上的空格。

这也是您遇到错误的原因。Ruby 无法解析你的行,因为你有两个方法调用。因此,第二个导致了错误:Ruby 需要关键字,但它遇到了另一个方法调用。end

在第二个括号中添加括号可以消除语法错误:

@@colors.index array[0] * 10 + @@colors.index(array[1])

但它可能不会给你你想要的结果。它将像这样解析它:

@@colors.index(array[0] * 10 + @@colors.index(array[1]))

因此,请为它们使用括号。我不确定你想做什么(不确定你想乘以 10 ),但像这样:

@@colors.index(array[0]) * 10 + @@colors.index(array[1])

通常,我更喜欢将参数括起来以方法调用。几乎唯一不使用它们的时候是 和 (编辑:以及我忘记了 Jörg 在下面的评论中添加的所有其他那些)。putsprintp

请注意不要在方法调用和打开的 paren 之间放置空格。

评论

3赞 Jörg W Mittag 10/12/2019
“几乎我唯一不使用它们的时候是 和 和 ”——标准的 Ruby 社区编码风格还建议不要对 、 、 、 、 和其他几个括号使用括号。putsprintprequirerequire_relativeloadincludeextendprependattr_readerattr_writerattr_accessor
0赞 BobRodes 10/12/2019
@JörgWMittag 你说得完全正确。我也不在那里使用它们!感谢您对答案的改进。