0

我喜欢偶尔使用 tap 作为方法返回的美化器。但是,当使用带有递归函数的 tap 时,它的行为与我的预期不同:

class Node
  attr_accessor :name, :children

  def initialize(name); self.name, self.children = name, []; end

  def render
    res = "Name: #{name}\n"
    children.each do |child|
      res += " - " + child.render + "\n"
    end
    res
  end
end

parent = Node.new('Parent')
parent.children = [Node.new('Child')]
puts parent.render

退货

Name: Parent
 - Name: Child

如果我将渲染功能更改为使用点击:

  def render
    "Name: #{name}\n".tap do |res|
      children.each do |child|
        res += " - " + child.render + "\n"
      end
    end
  end

它返回

Name: Parent

我会假设行为与第一个渲染函数相同。文档表明它“向块产生 x,然后返回 x”......因为函数正在递归,它是否以某种方式污染了函数堆栈?

4

1 回答 1

0

这与任何事情无关,只是赋值改变了一个变量,并且变量是按值传递的。tap无关紧要,如果将字符串放入任何变量中,则行为是相同的。

在您的情况下,您将字符串文字传递到 proc 中,该 proc 接收一个名为的变量,其中res包含该字符串的副本。然后,您正在修改该变量,而不是原始字符串本身。

考虑:

def test(res)
  res += "bar"
end

x = "foo"
test(x)
puts x # outputs "foo", not "foobar"

您的第一个示例有效的原因是您将字符串中的值替换res为新值。您实际上并没有将数据附加到存储在res.

于 2015-01-27T17:31:36.627 回答