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
Proc
sはメソッドとは異なる方法で呼び出されることに注意してください。
foo('Hello') # method
foo.('Hello') # Proc
構文は、 (sおよびsの場合も)のfoo.(bar)
構文糖衣です。オブジェクトにメソッドを実装してからそれを呼び出すことは、Pythonの機能に最も近いものです。foo.call(bar)
Proc
Method
foo[bar]
call
.()
__call__
RubyとPythonラムダの重要な違いProc
は、制限がないことです。Pythonでは、ラムダに含めることができるステートメントは1つだけですが、Rubyにはステートメントと式の区別がありません(すべてが式です)。したがって、この制限は単に存在しません。したがって、単一のステートメントでロジックを表現できないためにPythonで名前付き関数を引数として渡す必要がある多くの場合、RubyProc
では代わりにまたはブロックを渡すだけです。 、メソッドを参照するための醜い構文の問題が発生しないようにします。
オブジェクト(基本的にはduck-types )でメソッドをラップするには、オブジェクトでメソッドを呼び出します(これにより、その特定のオブジェクトにバインドされているが得られます)。Method
Proc
Object#method
Method
self
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)