私はレールを学んでおり、このスレッドに従っています。私はto_proc
方法に行き詰まっています。私はシンボルを文字列の代替としてのみ考えています (シンボルは文字列に似ていますが、メモリの点で安価です)。シンボルに欠けているものが他にある場合は、教えてください。to_proc
どういう意味で、何に使われるのか分かりやすく教えてください。
4 に答える
一部のメソッドはブロックを取り、このパターンはブロックに対して頻繁に表示されます。
{|x| x.foo}
そして人々はそれをもっと簡潔な方法で書きたいと思っています。そのために、シンボル、メソッドSymbol#to_proc
、暗黙的なクラスキャスト、および&
演算子の組み合わせを使用します。&
引数の位置にあるインスタンスの前に置くProc
と、それはブロックとして解釈されます。Proc
インスタンス以外のものをと組み合わせると、暗黙のクラスキャストは、存在する場合はそのオブジェクトで定義されたメソッドを使用して、それをインスタンス&
に変換しようとします。インスタンスの場合、次のように機能します。Proc
to_proc
Symbol
to_proc
:foo.to_proc # => ->x{x.foo}
たとえば、次のように記述したとします。
bar(&:foo)
演算子はインスタンスではない。と&
組み合わされるため、暗黙のクラスキャストが適用され、。が与えられます。これに適用され、ブロックとして解釈されます。これにより、次のようになります。:foo
Proc
Symbol#to_proc
->x{x.foo}
&
bar{|x| x.foo}
これを説明する最も簡単な方法は、いくつかの例です。
(1..3).collect(&:to_s) #=> ["1", "2", "3"]
以下と同じです:
(1..3).collect {|num| num.to_s} #=> ["1", "2", "3"]
と
[1,2,3].collect(&:succ) #=> [2, 3, 4]
以下と同じです:
[1,2,3].collect {|num| num.succ} #=> [2, 3, 4]
to_proc は、指定されたメソッドにシンボルで応答する Proc オブジェクトを返します。したがって、3 番目のケースでは、配列 [1,2,3] はその collect メソッドを呼び出します。succ はクラス Array によって定義されるメソッドです。したがって、このパラメーターは、配列内の各要素を収集し、その後続要素を返し、そこから [2,3,4] になる新しい配列を作成するという簡単な方法です。シンボル :succ は Proc オブジェクトに変換されるため、配列の succ メソッドを呼び出します。
私にとって最も明確な説明は、その単純な実装を見ることです。Symbol#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'
まだ少し困惑している人は、次のコードを実行すると、少しわかりやすくなるかもしれません。
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
これらはorの実際の実装ではなく、Array.map
単純化されたバージョンでありmap &:to_s
、同様の呼び出しがどのように機能するかを示すために使用しています。