0

我在理解为什么不能用圆括号调用 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

我正在使用红宝石 2.2.1。
有任何想法吗?

4

3 回答 3

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关键字进行评估。此博客文章中有更多信息。

lambda { 1 }.class # => Proc
于 2017-05-23T15:37:15.803 回答
2

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

波浪形括号也可用于在 ruby​​ 中创建哈希,这可能会引起一些混乱。

一些 ruby​​ 方法可以接受参数和块,在这种情况下,您可以在波浪形括号之前使用圆括号:EG

open("ChangeLog") { |f|
    f.slice_before(/\A\S/).each { |e| pp e }
}
于 2017-05-23T15:29:55.663 回答
1

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

因此,调用:

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

也可以用括号写成:

a.select() {|v| v.is_a? Integer }
于 2017-05-23T15:41:19.510 回答