to_proc 方法是啥意思?

Posted

技术标签:

【中文标题】to_proc 方法是啥意思?【英文标题】:What does to_proc method mean?to_proc 方法是什么意思? 【发布时间】:2013-01-30 15:02:25 【问题描述】:

我正在学习 rails 并关注 this thread。我坚持使用to_proc 方法。我仅将符号视为字符串的替代品(它们类似于字符串,但在内存方面更便宜)。如果我还缺少其他符号,请告诉我。请用简单的方式解释to_proc的含义和用途。

【问题讨论】:

其他答案非常适合回答如何在实践中使用to_proc。但是,我发现这些简单的文档链接可以更好地回答“它是什么”,包括“Proc 是什么”,这是 to_proc 返回的内容。 apidock.com/rails/Symbol/to_procruby-doc.org/core-2.2.0/Proc.html 【参考方案1】:

有些方法需要一个块,而这种模式经常出现在一个块中:

|x| x.foo

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

:foo.to_proc # => ->xx.foo

例如,假设你写:

bar(&:foo)

& 运算符与:foo 组合,后者不是Proc 实例,因此隐式类转换将Symbol#to_proc 应用于它,从而得到->xx.foo& 现在适用于此并被解释为一个块,它给出:

bar|x| x.foo

【讨论】:

另外,根据这个 thenewstack.io/…>,它在运行时快了 20 倍。 我明白&proc 给出了一个块,&x 导致 x 成为 proc 然后整个事情也给出了一个块。我也明白 Symbol 有 to_proc 方法。然而,我不明白的部分,我觉得这个答案缺乏,是符号和方法是如何连接的。我的意思是,并非所有方法都可以通过符号名称使用 @MuhammadUmer 您可以在对象上调用方法,例如1.to_s1.send(:to_s)。所以真的(1..10).each(&:to_s) 等价于(1..10).each |x| x.send(:to_s) 。该符号作为参数传递给send() 方法。看看这个link。 @MuhammadUmer 换句话说,是的,确实就像所有方法都可以通过符号名称使用。这就是 Ruby 在内部存储方法名称的方式。【参考方案2】:

用一些例子来解释这一点最简单的方法。

(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 方法。

【讨论】:

@Dilon +1 示例:)【参考方案3】:

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

【讨论】:

这并不完全准确,因为它创建了一个 lambda,而原始 Symbol#to_proc 没有。 @BobRodes 有趣,我没想过要检查。所以应该是Proc.new |object| object.send(self) ? 我也有这种感觉,试了一下。我会说它更接近,但是当我在irb 中运行它时,:foo.to_proc 的猴子补丁版本给了我这个:#<Proc:0x00007f8e132627a0@(irb):19>,而原始版本给了我这个:#<Proc:0x00007ffcb31d5fd0(&:foo)>。我尝试从名为test.rb 的文件中运行补丁并得到:#<Proc:0x00007fc4fa174f00@test.rb:35>。显然,在补丁版本中,self 指的是主环境而不是符号,所以它肯定有更多。 不过,我刚刚对其进行了测试,它似乎工作正常。测试是这种方法(由于我不完全清楚的原因,必须特别公开):public; def foo; "Hi, I'm foo."; end,这个调用:p [''].map(&:foo)。适用于原始版本和猴子补丁。【参考方案4】:

对于仍然有些困惑的人,运行以下代码可能会让事情变得更清晰:

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

【讨论】:

这正是我想要的!!!谢谢

以上是关于to_proc 方法是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

Python 中的 @withparser 方法是啥意思? [复制]

&&是啥意思

AtomicInteger类中getAndIncrement方法中的spin是啥意思?

ASSERT(SUCCEEDED(hr))是啥意思

groovy中的?.是啥意思

“方法存在但不满足特征界限”是啥意思?