获取 ruby​​ 函数对象本身

Posted

技术标签:

【中文标题】获取 ruby​​ 函数对象本身【英文标题】:Getting ruby function object itself 【发布时间】:2010-12-28 08:24:57 【问题描述】:

在 Ruby 中,一切都应该是一个对象。但是我有一个大问题要以通常的方式定义的函数对象,比如

def f
    "foo"
end

与 Python 不同,f 是函数结果,而不是函数本身。所以f()fObjectSpace.f都是"foo"f.methods 也只返回字符串方法列表。

如何访问函数对象本身?

【问题讨论】:

这是(许多)让我对红宝石发狂的事情之一。不调用函数就不能按名称引用它。我和我的奶牛工人对此有争论。 我认为 Ruby 有它自己的方式,其他语言中使用的一些原则根本不适用(在这种情况下,我可能会用 Proc 定义函数,或者使用代码块),但我仍然想知道我的问题是否有肯定的答案 @Jonathan:您可以引用方法的名称而不调用它。方法的名称是一个符号。所以这个方法的名字是:f。 Ruby 以其元编程功能而闻名,并且一直使用方法名称。 @Chuck 符号根本没有与函数耦合,它们只是轻量级的字符串对象(它们只有一小部分方法),用于代替常量.只要您可以将符号作为方法名称传递,您也可以根据需要传递字符串。 @dvyjones:我没有说它们与方法耦合。我说它们可以用来指代方法的名称,以回应 Jonathan 的说法,即“您不能通过名称来引用方法”。事实上,一个方法的名称不可能与之耦合,因为许多方法可以共享同一个名称。 【参考方案1】:

您只需使用method 方法。这将返回与该方法匹配的 Method 实例。一些例子:

>> 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, :[], ...]

希望这会有所帮助。

【讨论】:

哦,Method 对象是一个类似 Proc 的对象,所以你用obj.method(:f).call()obj.method(:f)[] 来调用它。或者,在 Ruby 1.9.1 上; obj.method(:f).().【参考方案2】:

method 方法会给你一个Method 对象

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

this f 绑定到 obj。你也可以得到一个未绑定的方法:

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

(还有一个unbind方法)

【讨论】:

所以你会说我的 f 是未绑定的方法。看起来很合理。然而,我的 f als 充当 ObjectSpace 方法(否则返回对象)的事实令人困惑 好吧,它仍然没有回答我的问题,我如何将我的 f 视为 Method 实例 @mykhal:您在顶层定义的任何方法都将成为 Object 的实例方法,因此 ObjectSpace(它是一个对象,就像语言中的其他所有内容一样)也可以获取该方法。但是,您通常不能从 ObjectSpace 外部调用它——以这种方式定义的方法默认为私有。【参考方案3】:

我自己找到了答案

obj = method :f

谢谢大家的启发:)

【讨论】:

这为您提供了方法,但不是纯函数。创建 Proc 对象可能更接近您想要的。一个方法总是需要一个接收者,因为它绑定到一个对象,一个过程(edure)本身就是一个对象,因此可以像函数一样被调用。 @Adrian 它提供了未绑定的方法。自己试试:ruby -e 'def f; "foo"; end; obj = method :f; puts obj.call'【参考方案4】:

在 Ruby 中,您所要求的没有意义。 (这在 Python、javascript、Java 和 C# 等语言中很有意义。)

在 Ruby 中,您可以告诉一个类它应该响应什么消息以及它应该以什么方式响应这些消息。告诉类最常用的方法就是在类中定义一个方法。但同样,这只是意味着:当有人向此实例发送消息 f 时,实例应该响应以下行为。没有函数对象。

您可以执行诸如获取符号 (method_name = :foo) 和获取闭包 (method = proc obj.foo ) 之类的操作。

【讨论】:

如果 f 不是一个对象,那为什么它在 ObjectSpace 中呢? 方法是对象。它们只是不是运行时允许您在它们仍在定义时访问的对象。如果您想这样做,请坚持使用 Python。 其实有一个Method类,所有的方法都是一个实例。当您在 Ruby 中执行 obj.some_method 时,它会将消息发送给 obj,obj 在其方法列表中查找匹配的方法,然后调用该方法。如果找不到方法,则调用method_missing【参考方案5】:

这不是函数;它是一个对象的方法。如果你想获得一个代表方法的对象,你可以向拥有它的对象询问:

someobj.method :f

例如:

plus_one = 1.method :+
plus_one[9] # 10

【讨论】:

def f; "foo"; end真的不是函数吗? 从概念上讲,不——它是一种方法。它本质上与 Ruby 中的所有者绑定。与真正的函数最接近的 Ruby 等价物是 Procs。【参考方案6】:

您可以在运行时获取与该函数对应的对象,但据我所知,没有与 Python 允许您在函数/类定义中直接执行的操作等效的对象。

希望有人能证明我错了,但我一直没能成功。

【讨论】:

【参考方案7】:

如果你想要一个函数对象,你应该创建一个Proc 对象

f = Proc.new  |x| x * 2 

您可以使用任一方法调用该函数

f.call(8) # => 16

f[8] # => 16

你甚至可以在map 操作中使用这个函数对象

[1, 2, 3, 4, 5].map(&f) # => [2, 4, 6, 8, 10]

【讨论】:

以上是关于获取 ruby​​ 函数对象本身的主要内容,如果未能解决你的问题,请参考以下文章

Function 对象属性和方法

Function 对象属性和方法

如何修复ruby中返回的不匹配对象类型?

JavaScript面向对象之函数构造器的理解

函数进阶之迭代器,递归

javascript中 原型对象中的 例如:obj.prototype.constructor指向错误,不是指向构造函数本身,那有啥影响?