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).
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.
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 :-)
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]
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.