Ruby to_proc破解绑定

时间:2009-12-29 09:30:31

标签: ruby-on-rails ruby binding

我正在尝试创建一个小的Ruby hack来制作类似Symbol#to_proc hack的反向。符号#to_proc hack使这成为可能:

some_array.each(&:some_method)

相同
some_array.each { |obj| obj.some_method }

我想让这成为可能:

some_array.each(&[:some_method])

相同
some_array.each { |obj| some_method(obj) }

问题是除非some_method是一个内核方法,否则它的真正含义是:

some_array.each { |obj| self.some_method(obj) }

当一个块被显式传递时,它会在写入这一行的绑定中创建,因此self可以正确访问当前对象,一切正常。但是,如果在Array的to_proc方法中创建块,则self在Array绑定中(并引用数组本身)。也许我不可能做我想做的事情,但我喜欢社区的一些想法。

到目前为止,这是我的黑客。只要该方法是内核方法,并且在Array:

中可用,这就可以工作
class Array
  def to_proc
    lambda {|i| send(self.first, i)}
  end
end

有了这个hack,这条线就可以工作了,并放了三个符号:

[:foo, :bar, :bas].each(&[:puts])

这对我来说很有用,因为我经常发现自己想要在控制台中检查一系列ActiveRecord对象,这样我就不会输入{| i |我把。但是能够在对象中使用它会更有用,这样对象中的某些方法就会被调用,并且数组中的每个项都作为参数传递。

那么任何想法如何使绑定问题有效?

请不要同时回答“你不想这样做,因为它会让事情变得更慢”或“你没有保存这么多的字符输入,但这会使代码的可读性降低” - 我已经知道这些事了。 :)这更像是一种喂养我好奇心的黑客行为。只是想知道是否可能。

3 个答案:

答案 0 :(得分:10)

您正在寻找名为method的方法:)

class Example
  def some(arg)
    p arg.size # just as a demo
  end
end

obj = Example.new
%w{the quick brown fox jumps over the lazy dog}.each(&obj.method(:some))

产量

3
5
5
3
5
4
3
4
3

答案 1 :(得分:3)

虽然Adrian在使用method方法时有正确的想法,但您可以进一步简化这一步骤:

# Works on any generic method
%w{the quick brown fox jumps over the lazy dog}.each(&method(:foo))

def foo(arg)
  p arg.size
end

# Works on user-defined methods, too
%w{the quick brown fox jumps over the lazy dog}.each(&method(:puts))

为什么不编写自己的Enumerable方法,而不是通过引入Array#to_proc来制作一些尴尬的语义呢?也许是这样的:

module Enumerable
  def pass_each(method_name)
    each(&method(method_name.to_sym))
  end
end

%w{the quick brown fox jumps over the lazy dog}.pass_each(:puts)

答案 2 :(得分:1)

这是另一种不使用method()方法:)的方法。它使用一个块来捕获绑定,然后在绑定的self上调用相关方法。

class Object
    def apply &block
        b = eval('self', block.binding)
        lambda { |param| b.send block.call, param }
    end
end


# use like this:
[1, 2, 3, 4].each &apply { :puts }

output: 1
        2
        3
        4