我喜欢偶尔使用水龙头作为方法返回的美化器。但是,当使用具有递归功能的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
如果我更改渲染功能以使用tap:
def render
"Name: #{name}\n".tap do |res|
children.each do |child|
res += " - " + child.render + "\n"
end
end
end
返回
Name: Parent
我认为行为与第一个渲染函数相同。文档指示它"产生x到块,然后返回x" ...因为函数递归是以某种方式污染函数堆栈?
答案 0 :(得分:0)
这与任何事情无关,除了赋值更改变量,变量按值传递。 tap
无关紧要,如果您将字符串放入任何变量,则行为相同。
在您的情况下,您将字符串文字传递给proc,它接收一个名为res
的变量,其中包含该字符串的副本。然后,您将修改该变量,不原始字符串本身。
考虑:
def test(res)
res += "bar"
end
x = "foo"
test(x)
puts x # outputs "foo", not "foobar"
您的第一个示例有效的原因是您使用新值替换字符串res
中的值。您实际上并未将数据附加到res
中存储的字符串。