Getting ruby function object itself

2020-02-28 18:06发布

In Ruby, everything is supposed to be an object. But I have a big problem to get to the function object defined the usual way, like

def f
    "foo"
end

Unlike in Python, f is the function result, not the function itself. Therefore, f(), f, ObjectSpace.f are all "foo". Also f.methods returns just string method list.

How do I access the function object itself?

7条回答
混吃等死
2楼-- · 2020-02-28 18:26

In Ruby, what you are asking for does not make sense. (It makes sense in languages like Python, JavaScript, Java, and C#.)

In Ruby, you can tell a class what messages it should respond to and in what ways it should respond to those messages. The most common way to tell a class that is to define a method in the class. But again, that simply means: when someone sends the message f to this instance, here's the behavior that the instance should respond with. There is no function object.

You can do things like get a symbol (method_name = :foo) and get a closure (method = proc { obj.foo }).

查看更多
家丑人穷心不美
3楼-- · 2020-02-28 18:32

The method method will give you a Method object

f = obj.method :f
puts f.call # or f[]

this f is bound to obj. You can also get an unbound method:

unbound_plus = Fixnum.instance_method('+')
plus_2 = unbound_plus.bind(2)

(There is also a unbind method)

查看更多
▲ chillily
4楼-- · 2020-02-28 18:33

You can obtain an object that will correspond to that function at runtime, but as far as I know there's no equivalent to what Python allows you to do right there in the function/class definition.

Hopefully someone will prove me wrong, but I've never been able to pull it off.

查看更多
我欲成王,谁敢阻挡
5楼-- · 2020-02-28 18:37

well I have found the answer myself

obj = method :f

thank you all for the inspiration :)

查看更多
疯言疯语
6楼-- · 2020-02-28 18:51

You simply use the method method. This will return the Method instance that matches with that method. Some examples:

>> def f
>>   "foo"
>> end
=> nil
>> f
=> "foo"
>> method(:f)
=> #<Method: Object#f>
>> method(:f).methods
=> [:==, :eql?, :hash, :clone, :call, :[], ...]
>> class SomeClass
>>   def f
>>     "bar"
>>   end
>> end
=> nil
>> obj = SomeClass.new
=> #<SomeClass:0x00000001ef3b30>
>> obj.method(:f)
=> #<Method: SomeClass#f>
>> obj.method(:f).methods
=> [:==, :eql?, :hash, :clone, :call, :[], ...]

Hope this helps.

查看更多
再贱就再见
7楼-- · 2020-02-28 18:51

You should create a Proc object if you want a function object

f = Proc.new { |x| x * 2 }

you call the function using either

f.call(8) # => 16

or

f[8] # => 16

you may even use this function object in a map operation

[1, 2, 3, 4, 5].map(&f) # => [2, 4, 6, 8, 10]
查看更多
登录 后发表回答