【问题标题】:Why am I getting an "Unexpected *" error when using the * (asterisk) operator as a method parameter?使用 *(星号)运算符作为方法参数时,为什么会出现“意外 *”错误?
【发布时间】:2017-01-31 21:54:28
【问题描述】:

我现在正在学习 Ruby,遇到了这种特殊情况。

当我运行以下代码时,我会得到下面进一步显示的输出。

工作代码:

def hello(a,b=1,*c,d,e,f)
  p a,b,c,d,e,f
end

hello(1,2,3,4,5)

工作代码输出:

1
2
[]
3
4
5

但是,在编辑代码以使参数“e”成为捕获所有参数时,我得到了下面进一步显示的错误。

失败代码:

def hello(a,b=1,c,d,*e,f)
    p a,b,c,d,e,f
end

hello(1,2,3,4,5)

失败的代码输出:

a.rb:1: syntax error, unexpected *
def hello(a,b=1,c,d,*e,f)
                     ^
a.rb:1: syntax error, unexpected ')', expecting '='
a.rb:3: syntax error, unexpected keyword_end, expecting end-of-input

我在 Ubuntu 上使用 ruby​​ 2.3.1p112(2016-04-26 修订版 54768)。

我很想知道为什么第二个 sn-p 代码会失败。

编辑:

以下代码也失败了。

def hello(a,b=1,c,d,e,*f)
    p a,b,c,d,e,f
end

hello(1,2,3,4,5)

我得到一个类似的错误

a.rb:1: syntax error, unexpected *
def hello(a,b=1,c,d,e,*f)
                       ^
a.rb:3: syntax error, unexpected keyword_end, expecting end-of-input

【问题讨论】:

  • 在末尾使用 splat 运算符对我来说没有意义。
  • 是的。它不可读,但可以解析它,Ruby 在某些情况下会这样做。
  • @fl00r 我尝试了以下方法定义,但我得到了同样的错误。 def hello(a,b=1,c,d,e,*f)

标签: ruby


【解决方案1】:

相关文档是here,这是一个相关的question。 但它们似乎并未涵盖所有情况。

这是我能收集到的:

  • 只能使用一个 splat 运算符 (*args)。
  • 可以使用多个默认参数 (a=1, b=2)。
  • 默认参数必须在 splat 运算符的左侧。
  • 多个默认参数必须一个接一个地直接出现。
  • 如果使用默认参数和 splat 运算符,则默认参数必须位于 splat 运算符之前。
  • 如果遵循上述规则,默认参数和 splat 运算符可以位于参数列表中的任何位置。

为了便于阅读,最好:

  • 将 splat 运算符作为最后一个参数
  • 避免将默认参数放在中间

以下是有效的方法定义:

def  hello(a = 1, b)            ;end
def  hello(a, b = 2)            ;end
def  hello(a = 1, b = 2)        ;end
def  hello(a = 1, b = 2, c)     ;end
def  hello(a, b = 2, c = 3)     ;end
def  hello(a, b = 2, *c)        ;end
def  hello(a, b = 2, *c, d)     ;end
def  hello(a = 1, b = 2, *c, d) ;end

对于你的第二个例子,这个语法会很好:

def hello(a,b,c,d=1,*e,f)
    p a,b,c,d,e,f
end

有关块和关键字参数的更完整示例,请参阅 @JörgWMittag 的优秀 answer

【讨论】:

  • 谢谢埃里克。这也是我的理解。我很困惑第二种情况对我不起作用。
  • @Steve 在您的第二个示例中,当恰好传递 5 个参数时,尚不清楚 b 应该作为 1 还是您的第二个参数传递。为了避免这些歧义,Ruby 强制执行这些更严格的规则。
  • 谢谢@HolgerJust。我的代码不符合 Eric 提到的以下规则。 如果使用默认参数和 splat 运算符,则默认参数必须在 splat 运算符之前。如果我遵循这个规则,代码就可以正常工作。
  • @HolgerJust:第二种方法并不比第一种更模棱两可。两者都很奇怪,恕我直言,不应该使用。第一个被 Ruby 接受,另一个不被接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-09
  • 2020-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-05
  • 1970-01-01
相关资源
最近更新 更多