web-dev-qa-db-ja.com

to_procメソッドはどういう意味ですか?

私はRailsとそれに続く このスレッド を学んでいます。to_proc 方法。シンボルは文字列の代替としてのみ考えます(文字列に似ていますが、メモリの点では安価です)。シンボルに不足しているものがあれば、教えてください。 to_procは、それが何に使用されるかを意味します。

44
swapnesh

一部のメソッドはブロックを取得し、ブロックに対してこのパターンが頻繁に表示されます。

{|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}
99
sawa

これを説明する最も簡単な方法は、いくつかの例を使用することです。

(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メソッドを呼び出します。

43
Dillon Benson

私にとって最も明確な説明は、それの簡単な実装を見ることです。 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'
8
Keith Bennett

まだ少し困惑している人のために、次のコードを実行すると少しわかりやすくなります。

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および同様の呼び出しがどのように機能するかを示すために使用している単純化されたバージョンです。

1
Gerry