【问题标题】:How can I fix this Ruby syntax error concerning the end keyword?如何修复这个关于 end 关键字的 Ruby 语法错误?
【发布时间】:2020-02-09 08:08:14
【问题描述】:

这是关于锻炼的问题。到目前为止,使每个解决方案都成为类方法似乎是一种奇怪的处理方式,但这不是我的主意。无论如何这里是代码:

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 关键字都得到了适当的平衡。我应该如何解决这个问题?

【问题讨论】:

  • 您可能希望使用括号来确保您的代码按预期进行评估。例如。我想你想要这样的东西:@@colors.index(array[0]) * 10 + @@colors.index(array[1])
  • 我的印象是括号在这种情况下是可选的。来自 Python(和 JS 以及我曾经使用过的几乎所有其他东西)的奇怪怪癖。但这确实解决了问题。将其发布为答案,我会接受。
  • 对于@dinjas 的评论,当您将@@colors.index array[1] 更改为@@colors.index(array[1]) 时,它会编译,但除此之外,我不确定您将括号可视化的位置。括号,即使可能不需要,也可以使您的代码更具可读性,并避免类似这样的错误。
  • @readyready15728 括号是可选的,但出于优先考虑,您不想在大多数情况下将它们排除在外。如果该语句在没有括号的情况下编译,它将按照@@colors.index((array[0] * 10) + @@colors.index(array[1])) 的行执行
  • @dinjas 我相信这是说它期望该行的其余部分成为第一个 index 方法的参数,之后它期望 end 关键字,但它得到了另一个带有空格参数的 index 方法调用。如果将第二个index 方法的参数括起来,错误就会消失。关于tIDENTIFIER 是什么的文档并不多,但是当省略引号或括号或其他内容时,通常会出现“意外的 tIDENTIFIER”错误。并不意味着 OP 遗漏了 end,而是它正在寻找 end 并遇到了其他问题。

标签: ruby syntax compiler-errors syntax-error


【解决方案1】:

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

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

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

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

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

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

我从 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])

一般来说,我更喜欢给方法调用的参数加上括号。几乎我唯一不使用它们的时间是 putsprintp(编辑:以及我忘记了 Jörg 在下面的 cmets 中添加的所有其他那些)。

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

【讨论】:

  • “几乎唯一一次我不使用它们的是putsprintp。” – 标准 Ruby 社区编码风格还建议不要在 requirerequire_relativeloadincludeextendprependattr_readerattr_writerattr_accessor 和其他几个。
  • @JörgWMittag 你说的完全正确。我也不在那里使用它们!感谢您对答案的改进。
【解决方案2】:

评论部分对@dinjas 的回答的补充

如果你有两个数组:

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

并在您的示例中执行类似操作:

colors.index array[0] * 10

你会得到#=&gt; 1,它是colors数组的第二个元素的索引10。这是因为 Ruby 将首先计算 array[0] * 10(即 1 * 10 = 10),然后检查 colors 数组中等于 10 的第一个元素的索引。

但是,如果您添加括号并执行以下操作:

 colors.index(array[0]) * 10

您将获得#=&gt; 0,因为colors 数组中等于1 (array[0] = 1) 的第一个元素的索引是00 * 10 = 0

前几天也有类似的问题,你可以去看看here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2020-02-18
    相关资源
    最近更新 更多