to_proc方法在Ruby中是什么意思?

ccgok5k5  于 2023-03-17  发布在  Ruby
关注(0)|答案(4)|浏览(168)

我正在学习rails并遵循this thread。我被to_proc方法卡住了。我认为符号只是字符串的替代品(它们像字符串,但在内存方面更便宜)。如果我对符号还有什么遗漏,请告诉我。请用简单的方式解释to_proc的含义和用途。

wvyml7n5

wvyml7n51#

有些方法需要一个块,对于一个块经常出现这种模式:

{|x| x.foo}

人们希望用一种更简洁的方式来写。为了做到这一点,他们使用了以下几种组合:符号、方法Symbol#to_proc、隐式类转换和&运算符。如果将&放在参数位置中Proc示例的前面,则会将其解释为块。如果将Proc示例以外的内容与&组合,则隐式类强制转换将尝试使用在该对象上定义的to_proc方法(如果有)将其转换为Proc示例。在Symbol示例的情况下,to_proc以如下方式工作:

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

例如,假设您编写:

bar(&:foo)

&运算符与:foo组合在一起,而:foo不是Proc示例,因此隐式类转换将Symbol#to_proc应用于它,从而得到->x{x.foo}&现在应用于此运算符,并解释为一个块,从而得到:

bar{|x| x.foo}
euoag5mw

euoag5mw2#

最简单的解释方法是举几个例子。

(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是Integer类定义的方法。因此,此参数是收集数组中的每个元素并返回其后继元素,然后从该元素创建一个新数组,结果为[2,3,4]。符号:succ被转换为Proc对象,因此它调用Array的succ方法。

cig3rfwq

cig3rfwq3#

对我来说,最清楚的解释是看到它的一个简单实现,如果我重新实现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'
5n0oy7gb

5n0oy7gb4#

对于那些还有点困惑的人来说,运行下面的代码可能会让事情变得更清楚一些:

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和类似调用如何工作的简化版本。

相关问题