web-dev-qa-db-fra.com

Qu'est-ce que la récursivité et comment ça marche?

Quelqu'un pourrait-il expliquer ce qu'est exactement la récursivité (et comment cela fonctionne dans Ruby, si ce n'est pas trop demander). Je suis tombé sur un long extrait de code reposant sur la récursivité et cela m'a confondu (je l'ai perdu maintenant, et ce n'est pas tout à fait pertinent).

19
omninonsense

Une fonction/méthode récursive s'appelle elle-même. Pour qu'un algorithme récursif se termine, vous avez besoin d'un cas de base (par exemple, une condition dans laquelle la fonction pas s'appelle récursivement) et vous devez également vous assurer que vous vous rapprochez de ce cas de base à chaque appel récursif. . Regardons un exemple très simple:

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

Certains problèmes peuvent être exprimés de manière très élégante avec la récursivité, par exemple beaucoup de fonctions mathématiques sont décrites de manière récursive.

62
Michael Kohl

Pour comprendre la récursivité, vous devez d'abord comprendre la récursivité.

Maintenant, sur une note sérieuse, une fonction récursive est celle qui s'appelle elle-même. Un exemple classique de cette construction est la séquence des fibonacci:

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

L'utilisation de fonctions récursives vous donne une grande puissance, mais est également livré avec beaucoup de responsabilité (jeu de mots prévu) et présente un certain risque. Par exemple, vous pourriez vous retrouver avec des débordements de pile (je suis sur une lancée) si votre récursivité est trop grande :-)

33
changelog

Ruby on Rails exemple:

La récursivité générera un éventail de parents parents

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

console :

d = Document.last
d.ancestors.collect(&:id)
# => [570, 569, 568] 

https://Gist.github.com/equivalent/506377

4
equivalent8

En règle générale, la récursivité consiste à appeler des méthodes, mais peut-être que vous avez rencontré des structures récursives, c'est-à-dire des objets se référant à eux-mêmes. Ruby 1.9 les gère très bien:

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

Je trouve que la dernière ligne est assez méchante; I blogué sur ce genre de problèmes avec la comparaison des structures récursives il y a quelques années.

2