Rubyには機能がありません。メソッド(ファーストクラスではない)とProcファーストクラスであるが、どのオブジェクトにも関連付けられていないメソッドのみがあります。
だから、これは方法です:
def foo(bar) puts bar end
foo('Hello')
# Hello
ああ、そうです、これは実際のメソッドであり、トップレベルの関数やプロシージャなどではありません。トップレベルで定義されたメソッドは、最終的にObjectクラス内のprivate(!)インスタンスメソッドになります。
Object.private_instance_methods(false) # => [:foo]
これはProc:
foo = -> bar { puts bar }
foo.('Hello')
# Hello
Procsはメソッドとは異なる方法で呼び出されることに注意してください。
foo('Hello') # method
foo.('Hello') # Proc
構文は、 (sおよびsの場合も)のfoo.(bar)構文糖衣です。オブジェクトにメソッドを実装してからそれを呼び出すことは、Pythonの機能に最も近いものです。foo.call(bar)ProcMethodfoo[bar]call.()__call__
RubyとPythonラムダの重要な違いProcは、制限がないことです。Pythonでは、ラムダに含めることができるステートメントは1つだけですが、Rubyにはステートメントと式の区別がありません(すべてが式です)。したがって、この制限は単に存在しません。したがって、単一のステートメントでロジックを表現できないためにPythonで名前付き関数を引数として渡す必要がある多くの場合、RubyProcでは代わりにまたはブロックを渡すだけです。 、メソッドを参照するための醜い構文の問題が発生しないようにします。
オブジェクト(基本的にはduck-types )でメソッドをラップするには、オブジェクトでメソッドを呼び出します(これにより、その特定のオブジェクトにバインドされているが得られます)。MethodProcObject#methodMethodself
foo_bound = method(:foo)
foo_bound.('Hello')
# Hello
Module#instance_methodファミリ内のメソッドの1つを使用してUnboundMethod、モジュール(または、クラスはモジュールであるため、明らかにクラス)から取得することもできます。これUnboundMethod#bindにより、特定のオブジェクトを呼び出して呼び出すことができます。(Pythonの概念は同じだと思いますが、実装は異なります。バインドされていないメソッドは、宣言された方法と同じように、自己引数を明示的に取ります。)
foo_unbound = Object.instance_method(:foo) # this is an UnboundMethod
foo_unbound.('Hello')
# NoMethodError: undefined method `call' for #<UnboundMethod: Object#foo>
foo_rebound = foo_unbound.bind(self) # this is a Method
foo_rebound.('Hello')
# Hello
UnboundMethodメソッドを取得したモジュールのインスタンスであるオブジェクトにのみバインドできることに注意してください。UnboundMethods無関係なモジュール間で動作を「移植」するために使用することはできません。
bar = module Foo; def bar; puts 'Bye' end; self end.instance_method(:bar)
module Foo; def bar; puts 'Hello' end end
obj = Object.new
bar.bind(obj)
# TypeError: bind argument must be an instance of Foo
obj.extend(Foo)
bar.bind(obj).()
# Bye
obj.bar
# Hello
ただし、とは両方ともMethodメソッドUnboundMethodのラッパーであり、メソッド自体ではないことに注意してください。メソッドはRubyのオブジェクトではありません。(私が他の回答で書いたこととは反対に、ところで。私は本当に戻ってそれらを修正する必要があります。)それらをオブジェクトでラップすることはできますが、それらはオブジェクトではありません。ラッパーで常に発生する問題:IDと状態。method同じメソッドを複数回呼び出すと、Method毎回異なるオブジェクトが取得されます。そのオブジェクトに状態を保存しようとしたMethod場合(Pythonスタイルなど)__doc__文字列など)、その状態はその特定のインスタンスに対してプライベートになり、を介してdocstringを再度取得しようとするとmethod、それがなくなっていることがわかります。
メソッド参照演算子.:の形式の構文糖衣もあります。
bound_method = obj.:foo
これはと同じです
bound_method = obj.method(:foo)