Ruby 什么是递归?它是如何工作的?

Ruby 什么是递归?它是如何工作的?,ruby,recursion,Ruby,Recursion,请有人解释一下递归到底是什么(以及它在Ruby中是如何工作的,如果这个要求不高的话)。我遇到了一个依赖递归的冗长代码片段,这让我很困惑(我现在把它弄丢了,它并不完全相关)。要理解递归,首先需要理解递归 现在,严肃地说,递归函数是一个调用自身的函数。这种构造的一个经典示例是斐波那契序列: def fib(n) return n if (0..1).include? n fib(n-1) + fib(n-2) if n > 1 end 使用递归函数给您带来了强大的功能,但同时也带来了

请有人解释一下递归到底是什么(以及它在Ruby中是如何工作的,如果这个要求不高的话)。我遇到了一个依赖递归的冗长代码片段,这让我很困惑(我现在把它弄丢了,它并不完全相关)。

要理解递归,首先需要理解递归

现在,严肃地说,递归函数是一个调用自身的函数。这种构造的一个经典示例是斐波那契序列:

def fib(n)
  return n if (0..1).include? n
  fib(n-1) + fib(n-2) if n > 1
end

使用递归函数给您带来了强大的功能,但同时也带来了很多责任(双关语),并且会带来一些风险。例如,如果递归性太大,可能会导致堆栈溢出(我很忙):-)

递归函数/方法会调用自身。对于要终止的递归算法,您需要一个基本情况(例如,函数不递归调用自身的条件),并且您还需要确保在每次递归调用中都更接近该基本情况。让我们看一个非常简单的例子:

def countdown(n)
  return if n.zero? # base case
  puts n
  countdown(n-1)    # getting closer to base case 
end               

countdown(5)
5
4
3
2
1

有些问题可以用递归非常优雅地表达,例如许多数学函数都是以递归的方式描述的。

通常递归是关于方法调用自身,但可能遇到的是递归结构,即对象引用自身。Ruby 1.9很好地处理了这些问题:

h = {foo: 42, bar: 666}
parent = {child: {foo: 42, bar: 666}}
h[:parent] = parent
h.inspect # => {:foo=>42, :bar=>666, :parent=>{:child=>{...}}}

x = []
y = [x]
x << y
x.inspect # => [[[...]]]
x == [x]  # => true
h={foo:42,bar:666}
父项={子项:{foo:42,bar:666}
h[:父项]=父项
h、 检查#=>{:foo=>42,:bar=>666,:parent=>{:child=>{…}}
x=[]
y=[x]
x[…]]
x==[x]#=>真

我发现最后一行很邪恶;我在几年前通过对递归结构的比较了解了这类问题。

RubyonRails示例:

递归将生成父数组

a/m/document.rb

class Document < ActiveRecord::Base

  belongs_to :parent, class_name: 'Document'

  def self.get_ancestors(who)
    @tree ||= []
    # @tree is instance variable of Document class object not document instance object
    # so: Document.get_instance_variable('@tree')

    if who.parent.nil?
      return @tree
    else
      @tree << who.parent
      get_ancestors(who.parent)
    end
  end

  def ancestors
    @ancestors ||= Document.get_ancestors(self)
  end

end

如果你把代码弄混了,代码怎么会不相关呢?递归是计算中的一个普遍原则,可以在大多数语言中执行,它不是RubyYou are right@changeloge的特定概念。很久以前,在玩irb的时候,我使用上面的代码和大斐波那契序列“55”时,超过5分钟没有得到结果。我发现散列的速度更快,比如fibonacci=Hash.new{h,k{h[k]=k<2?k:h[k-1]+h[k-2]}
d = Document.last
d.ancestors.collect(&:id)
# => [570, 569, 568]