2

红宝石世界的初学者,我想做类似的事情:

[1,2.0,"a",2].select(&:is_a?(Integer))

但像这样它绝对行不通......

有任何想法吗?

4

2 回答 2

2

你不能做你要求的事情,因为当你使用&语法时,你必须使用不带参数的方法。

但是,如果您出于某种原因确实想做这样的事情,则需要创建一个不采用如下参数的方法:

class Object
  def is_an_integer?
   is_a? Integer
  end
end

然后你可以这样做:

[1,2.0,"a",2].select(&:is_an_integer)
于 2013-07-13T17:32:43.417 回答
1

&:method_name是 . 的语法糖&:method.to_proc。枚举器喜欢select和不接受一个块并将枚举器的每个元素产生给传递的块。那是:

[1,2,3].select &:even?

相当于:

p = :even.to_proc
[1,2,3].select {|val| p.yield(val) }

由于只有枚举器产生的参数才会产生给 proc,因此您必须将它们包含在源列表中。也就是说,我们可能期望:

[[1, Integer]].select &:is_a?

以导致:

select {|*args|, p.yield(*args) }

但是,请记住,这p不是绑定到任何特定类的方法!它将尝试在传递的参数上调用给定的方法。因此,它将尝试Array#is_a?不带参数调用,而不是把参数喷出来并调用Integer#is_a?(Integer).

因此,为了实现这一点,我们必须以某种方式创建一个绑定传递参数的 proc,然后使用传递的参数调用产生的接收器上的给定方法。我们可以通过向 Symbol 类添加一个方法来做到这一点:

  class Symbol
    def with_args(*args)
      proc {|receiver| receiver.send(self, *args) }
    end
  end

  [1, "a"].select &:is_a?.with_args(Integer)

虽然它可能不是非常干净,但它确实有效。

于 2013-07-13T17:40:45.583 回答