to_proc方法是什么意思?

时间:2013-02-14 17:58:43

标签: ruby syntax block symbols proc

我正在学习rails并关注this thread。我坚持使用to_proc方法。我认为符号只是字符串的替代品(它们就像字符串,但在内存方面更便宜)。如果还有其他我想念的符号,那么请告诉我。请以简单的方式解释to_proc的含义及其用途。

4 个答案:

答案 0 :(得分:94)

某些方法会占用一个块,这种模式经常出现在块中:

{|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}}现在适用于此并被解释为一个块,它给出了:

{{1}}

答案 1 :(得分:43)

最简单的解释方法是举一些例子。

(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对象,它按符号响应给定的方法。 所以在第三种情况下,数组[1,2,3]调用它的collect方法和。 succ是由类Array定义的方法。所以这个参数是一种简单的说法,收集数组中的每个元素并返回它的后继,并从中创建一个新的数组,产生[2,3,4]。符号:succ正在转换为Proc对象,因此它调用了Array的succ方法。

答案 2 :(得分:8)

对我而言,最清楚的解释是看到它的简单实现。这是我重新实现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'

答案 3 :(得分: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_procArray.map的实际实现,它们只是我用来演示map &:to_s和类似调用如何工作的简化版本。