我正在尝试创建一个小的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 |我把。但是能够在对象中使用它会更有用,这样对象中的某些方法就会被调用,并且数组中的每个项都作为参数传递。
那么任何想法如何使绑定问题有效?
请不要同时回答“你不想这样做,因为它会让事情变得更慢”或“你没有保存这么多的字符输入,但这会使代码的可读性降低” - 我已经知道这些事了。 :)这更像是一种喂养我好奇心的黑客行为。只是想知道是否可能。
答案 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