58

私はレールを学んでおり、このスレッドに従っています。私はto_proc方法に行き詰まっています。私はシンボルを文字列の代替としてのみ考えています (シンボルは文字列に似ていますが、メモリの点で安価です)。シンボルに欠けているものが他にある場合は、教えてください。to_procどういう意味で、何に使われるのか分かりやすく教えてください。

4

4 に答える 4

114

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

{|x| x.foo}

そして人々はそれをもっと簡潔な方法で書きたいと思っています。そのために、シンボル、メソッドSymbol#to_proc、暗黙的なクラスキャスト、および&演算子の組み合わせを使用します。&引数の位置にあるインスタンスの前に置くProcと、それはブロックとして解釈されます。Procインスタンス以外のものをと組み合わせると、暗黙のクラスキャストは、存在する場合はそのオブジェクトで定義されたメソッドを使用して、それをインスタンス&に変換しようとします。インスタンスの場合、次のように機能します。Procto_procSymbolto_proc

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

たとえば、次のように記述したとします。

bar(&:foo)

演算子はインスタンスではない。と&組み合わされるため、暗黙のクラスキャストが適用され、。が与えられます。これに適用され、ブロックとして解釈されます。これにより、次のようになります。:fooProcSymbol#to_proc->x{x.foo}&

bar{|x| x.foo}
于 2013-02-14T18:21:46.500 に答える
47

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

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

于 2013-02-14T18:38:23.560 に答える
7

私にとって最も明確な説明は、その単純な実装を見ることです。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'
于 2015-03-12T15:41:13.900 に答える
2

まだ少し困惑している人は、次のコードを実行すると、少しわかりやすくなるかもしれません。

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、同様の呼び出しがどのように機能するかを示すために使用しています。

于 2016-04-26T05:48:58.487 に答える