使用圆括号抛出语法错误

时间:2017-05-23 15:24:16

标签: ruby select methods syntax ruby-block

我很难理解为什么我不能用圆括号调用select。

a = [1,2,3]
a.select {|v| v.is_a?(Integer)}  # works
a.select({|v| v.is_a?(Integer)}) # syntax error, unexpected '|', expecting '}

据我所知,select是一种常规方法。

Array.method_defined? :select # true
Array.method_defined? :is_a?  # true

我认为圆形括号对于ruby中的方法是可选的 在下面的情况下,圆括号没有区别。

a.reverse() == a.reverse #true

我使用ruby 2.2.1。
有什么想法吗?

3 个答案:

答案 0 :(得分:4)

你不能通过这样的synatx传递一个块,你必须做这样的事情:

a.select(&lambda { |v| v.is_a?(Integer) })

但通常你会这样做

a.select { |v| v.is_a?(Integer) }

相同
a.select() { |v| v.is_a?(Integer) }

,即该块在方法参数之外。

你也可以使用'stabby'lambda语法:

is_a_integer = ->(v) { v.is_a?(Integer) }
a.select(&is_a_integer)

因此,如果您想要将块作为参数传递,则需要使用&作为前缀,但由于无神论的原因,通常您会在参数之外使用该块。

还要注意这些与方法签名之间的区别以及它们的调用方式:

def call(&block)
  yield
end

call { 1 } # => 1

call(lambda { 1 }) # => ArgumentError

call(&lambda { 1 }) # => 1

def call(block)
  block.call
end

call { 1 } # => ArgumentError

call(lambda { 1 }) # => 1

call(&lambda { 1 }) # => ArgumentError

这是因为lambda(和Procs)是对象,因此我们可以#call来评估它们,但是块不是并且可以使用yield关键字来评估。 this blog post中有更多信息。

lambda { 1 }.class # => Proc

答案 1 :(得分:2)

圆括号是一种将参数传递给方法的方法,而波浪形括号(或do / end)是将块传递给方法的一种方法。它们不可互换。

Squiggly括号也可用于在ruby中创建哈希,这可能会引起一些混淆。

一些ruby方法可以使用参数和块,在这种情况下,您可以在波浪形括号之前使用圆括号:E.G。

open("ChangeLog") { |f|
    f.slice_before(/\A\S/).each { |e| pp e }
}

答案 2 :(得分:1)

有或没有括号,Array#select不接受任何常规参数。然而,它接受一个块参数,但是与方法调用相关联的块总是放在括号之后,而不是在它们内部。

因此,电话:

a.select {|v| v.is_a? Integer }

也可以用括号写成:

a.select() {|v| v.is_a? Integer }