Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 递归函数的tap行为_Ruby_Recursion_Combinators - Fatal编程技术网

Ruby 递归函数的tap行为

Ruby 递归函数的tap行为,ruby,recursion,combinators,Ruby,Recursion,Combinators,我喜欢偶尔使用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 += " -

我喜欢偶尔使用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”……因为函数正在递归,它是否污染了函数堆栈?

这与任何事情都无关,只是赋值改变了变量,变量按值传递
tap
是不相关的,如果将字符串放入任何变量中,行为是相同的

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

考虑:

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

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

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

string
中的字符串中,Ruby中的字符串是非常可变的。
String
上有很多变异方法:
字符串不是不可变的,但是无论何时使用赋值运算符,实际上都是在更改
=
左侧引用的对象,而不是更改该对象的值。