递归函数的 tap 行为
Behaviour of tap for recursive functions
我喜欢偶尔使用 tap 作为方法的美化器 returns。但是,当使用带递归函数的 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
Returns
Name: Parent
- Name: Child
如果我将渲染函数更改为使用 tap:
def render
"Name: #{name}\n".tap do |res|
children.each do |child|
res += " - " + child.render + "\n"
end
end
end
它returns
Name: Parent
我假设行为与第一个渲染函数相同。文档表明它 "Yields x to the block, and then returns x"...因为函数是递归的,它是否以某种方式污染了函数堆栈?
这除了赋值改变一个变量外,没有任何关系,变量是按值传递的。 tap
无关紧要,如果将字符串放入 any 变量中,行为是相同的。
在您的例子中,您将一个字符串文字传递给一个 proc,它接收一个名为 res
的变量,其中包含该字符串的一个副本。然后您要修改该变量,不是原始字符串本身。
考虑:
def test(res)
res += "bar"
end
x = "foo"
test(x)
puts x # outputs "foo", not "foobar"
您的第一个示例起作用的原因是您用新值替换 字符串res
中的值。您实际上并没有将数据附加到存储在 res
.
中的字符串
我喜欢偶尔使用 tap 作为方法的美化器 returns。但是,当使用带递归函数的 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
Returns
Name: Parent
- Name: Child
如果我将渲染函数更改为使用 tap:
def render
"Name: #{name}\n".tap do |res|
children.each do |child|
res += " - " + child.render + "\n"
end
end
end
它returns
Name: Parent
我假设行为与第一个渲染函数相同。文档表明它 "Yields x to the block, and then returns x"...因为函数是递归的,它是否以某种方式污染了函数堆栈?
这除了赋值改变一个变量外,没有任何关系,变量是按值传递的。 tap
无关紧要,如果将字符串放入 any 变量中,行为是相同的。
在您的例子中,您将一个字符串文字传递给一个 proc,它接收一个名为 res
的变量,其中包含该字符串的一个副本。然后您要修改该变量,不是原始字符串本身。
考虑:
def test(res)
res += "bar"
end
x = "foo"
test(x)
puts x # outputs "foo", not "foobar"
您的第一个示例起作用的原因是您用新值替换 字符串res
中的值。您实际上并没有将数据附加到存储在 res
.