2016-07-13 11 views
1

Rubyにはファーストクラスの関数はありません。それはprocsとlambdaを持っていますが、これらにはかなりのオーバーヘッドが必要です。 (Pythonは明らかにオーバーヘッドなしに、ファーストクラスの機能を持っています。) それは匿名クラスを使用して、もう少し作業をシミュレートすることができる第一級関数に私を発生し、次のように:ファーストクラスの関数としてのRubyの匿名クラス

f = Class.new { def self.f; puts 'hi'; end } 

def g(fun); fun; end 

g(f.f) 
# => "hi" 

は誰もが知っているより良いです方法?

+1

「より良い」とはどういう意味ですか?あなたは何を達成しようとしていますか?より速いスピードか、あるいはいくつかの追加機能? –

+4

上記のコードで 'g(f.f)'を呼び出すと、 'g'に渡す引数は関数ではありません。メソッド 'f.f'を呼び出して、結果を返す文字列' 'hi ''を 'g'に渡します。これは単に引数を返します。 –

+2

@Jordan実際に 'puts'は' nil'を返します。したがって、 'g(f.f)'は引数として 'nil'をとります。 – Aetherus

答えて

6

実際、Rubyには関数が全くなく、メソッドだけがあります。だから、あなたが別のメソッドにメソッドを渡したい場合は、これは、Python未満簡潔

def g(f) 
    f.call 
end 

g('123'.method(:to_i)) 

であることができますが、それはRubyはメソッド呼び出しに括弧を省略する能力を支払わなければならない価格です。私は括弧を省略することがRubyを輝かせるものの1つだと考えています。これは純粋なRubyでDSLをもっと簡単に実装できるようにするためです。

+0

私はDSLの実装についてのあなたの発言を理解していませんが、興味深いと思います。メソッドが最初にprocに変換された場合、procは 'g 'に渡すことができます:proc =' 123'.method(:to_i).to_proc #=>#; g(proc)#=> 123'となります。 –

1

Rubyはproc sおよびlambda S(Procクラスの両方のインスタンス)、およびMethod S、全てのおおよそのファーストクラスの機能を有しています。 Lambdaは真のファーストクラスの関数に最も近い関数です。コールされたときに引数の数をチェックし、returnがラムダから返るような新しいコールコンテキストを作成します。これとは対照的に、procsは単なるコードブロックです。彼らは引数の数をチェックせず、returnは、囲みメソッドがprocだけでなく戻るようにします。

メソッドオブジェクトを使用すると、呼び出されていないメソッドを変数に格納し、暗黙のinvocantで完了することができます。匿名メソッドを作成するための構文はありませんが、匿名メソッドではなく、ファーストクラスの関数があります。 invocant以外のものは基本的に参照されるメソッドの本体であるlambdaです。

匿名のクラスがあなたに得られるものは、上記の解決策よりも優れていますが、実際のファーストクラスの機能からはさらに離れています。クロージャーが言語に追加される前に、Javaでそれらを近似する必要があったのと同じです。

関連する問題