Ruby左对抗右递归

时间:2014-04-30 17:32:52

标签: ruby parsing recursion internals

由于某种原因,Ruby在面向左递归时似乎表现更好。例如:

def left_recursive_factorial(number)
  return 1 if number.zero?
  left_recursive_factorial(number.pred) * number
end

def right_recursive_factorial(number)
  return 1 if number.zero?
  number * right_recursive_factorial(number.pred)
end

当我使用超过9000()的值调用这些方法时,我会得到不同的结果:

left_recursive_factorial(9001)
  # => factorial of 9001

right_recursive_factorial(9001)
  # => SystemStackError: stack level too deep
  #    from (pry):6:in `right_recursive_factorial'

我无法找到这种行为的任何解释。

唯一似乎有点相关的是关于LL()解析器左移递问题,我猜你可以翻转它,但我还没有挖掘它。

有人可以更详细地解释是什么导致左右递归以不同的方式执行(通常在Ruby中),如果你有可能选择其中一个为什么你会选择它(为什么选择左边?在Ruby)?

1 个答案:

答案 0 :(得分:6)

好吧,我不是任何类型的YARV黑客,但这是我所理解的差异。当您调用方法时,发送方将方法的参数推送到堆栈,然后被调用的方法将其参数弹出并推送其返回值。首先使用递归调用,number参数尚未被压入堆栈,因此每次调用的堆栈占用的空间略小。这就是为什么你可以从该版本中获得更多的迭代,但不是更多 - 你正在考虑减少几个百分点的堆栈使用。