2013-02-14 9 views
31

私はレールを学び、this threadに従っています。私はto_procメソッドで立ち往生しています。私は記号を文字列の代わりに使うことを考えています(文字列のようですが、メモリの点では安い)。私がシンボルに欠けているものが他にあれば、教えてください。簡単な方法で、to_procの意味とその意味を説明してください。to_procメソッドとはどういう意味ですか?

答えて

77

いくつかの方法は、ブロックを取り、このパターンが頻繁にブロックごとに表示されます。

{|x| x.foo} 

、人々はより簡潔な方法でそれを書きたいと思います。これを行うには、シンボルSymbol#to_proc、暗黙のクラスキャスティング、および&演算子を組み合わせて使用​​します。引数の位置にあるProcインスタンスの前に&を置くと、ブロックとして解釈されます。 Proc以外のインスタンスと&を組み合わせた場合、暗黙のクラスキャストは、そのオブジェクトに定義されているメソッドto_procを使用してProcインスタンスに変換しようとします。 Symbol例えば、このようにto_proc作品の場合:たとえば

:foo.to_proC# => ->x{x.foo} 

、あなたはこのように書くとします

bar(&:foo) 

&オペレータがProcインスタンスされていない、:fooと組み合わされ暗黙のクラスキャストではSymbol#to_procが適用され、->x{x.foo}となります。 &は今、これに適用され、与えブロック、のように解釈されます。

bar{|x| x.foo} 
+3

ありがとうございます+1: – swapnesh

+0

さらに、このによると、20実行時にはより高速に実行できます。 –

+0

私は '&proc'がブロックを与えていることを理解しています、'&x'はxがprocになり、全体がブロックになります。 Symbolにはto_procメソッドがあることも理解しています。しかし、私が理解していない部分と私はこの答えが欠けていると感じています、どのようにシンボルとメソッドが接続されています。つまり、すべてのメソッドがシンボル名でも利用できるようではありません。 –

39

をこれを説明する最も簡単な方法は、いくつかの例です。所定の方法に応答PROCオブジェクトを返すto_proc

[1,2,3].collect {|num| num.succ} #=> [2, 3, 4] 

(1..3).collect {|num| num.to_s} #=> ["1", "2", "3"] 

[1,2,3].collect(&:succ) #=> [2, 3, 4] 

と同じです:

(1..3).collect(&:to_s) #=> ["1", "2", "3"] 

は同じですシンボルによって。 3番目のケースでは、配列[1,2,3]はそのcollectメソッドとを呼び出します。 succはArrayクラスで定義されたメソッドです。したがって、このパラメータは、配列内の各要素を収集してその後継者を返し、それから新しい配列を作成して[2,3,4]という結果をもたらすという簡単な方法です。シンボル:succがProcオブジェクトに変換されているため、配列のsuccメソッドが呼び出されます。

+3

@Dilon +1例: – swapnesh

7

私にとって、わかりやすい説明は簡単な実装です。ここでは、私はシンボル#のto_procを再実装された場合、それはどのように見えるかです:

class Symbol # reopen Symbol class to reimplement to_proc method 
    def to_proc 
    ->(object) { object.send(self) } 
    end 
end 

my_lambda = :to_s.to_proc 

puts my_lambda.(1) # prints '1'; .() does the same thing as .call() 
puts my_lambda.(1).class # prints 'String' 

puts [4,5,6].map(&:to_s) # prints "4\n5\n6\n" 
puts [4,5,6].map(&:to_s).first.class # prints 'String' 
+1

これ!ところで、あなたは 'Symbol'クラスの猿パッチにしようとしているメソッドの' my_to_proc'ではないでしょうか? –

+0

@AgungSetiawan良いキャッチ!代わりに、私は、呼び出しをmy_to_procではなくto_procを呼び出すように変更しました。 –

1

まだ少し困惑誰のために、次のコードを実行すると、物事が少し明確になるかもしれない:

class Symbol 
    def to_proc 
    proc do |obj| 
     puts "Symbol proc: #{obj}.send(:#{self})" 
     obj.send(self) 
    end 
    end 
end 

class Array 
    def map(&block) 
    copy = self.class.new 
    self.each do |index| 
     puts "Array.map: copy << block.call(#{index})" 
     copy << block.call(index) 
    end 
    copy 
    end 
end 

remapped_array = [0, 1, 2].map &:to_s 
puts "remapped array: #{remapped_array.inspect}" 

これらはありませんSymbol.to_procまたはArray.mapの実際の実装では、これらは単にmap &:to_sなどの呼び出しがどのように機能するかを示すために使用している単純化されたバージョンです。

関連する問題