Licence CC BY-NC-ND

Séquences infinies en Ruby

Juste un petit billet pour parler rapidement des séquences « infinies » en Ruby qui se font notamment grâce à la classe Enumerator. Quand on parle de séquences infinies, en fait, il s’agit d’être paresseux et de ne calculer les choses que quand y en a besoin.

Un exemple est la classe Prime pour les nombres premiers. p.next nous donne le prochain nombre premier.

p = Prime.each
10.times { puts p.next }
puts p.take(10)

Avec la méthode lazy, on transforme un objet énumérable en Enumerator paresseux. Les éléments ne seront donc calculés que si nécessaires.

l = (1..Float::INFINITY).lazy.map { |x| 2 * x }
10.times { puts l.next }

Ici, le calcul du map ne sera fait que pour les 10 premiers éléments de la liste (car on en a besoin, on a demandé les valeurs).

Mais dans ce billet, je voulais surtout poster un petit test rigolo. Avec des lambdas, je définis la fonction exponentielle par sa somme

exp(x)=k=0+xkk!. \exp (x) = \sum_{k = 0}^{+\infty} \frac{x^k}{k!}.
def subexp
  (0..Float::INFINITY).lazy.map do |k| 
    lambda { |x| x**k / Math.gamma(k + 1) }
  end
end

exp = lambda { |x| (subexp.map { |f| f.call(x) }).sum }

# puts exp(2)

Et voilà, un code qui mélange lambdas et Enumerator. Bien sûr, ça ne va pas trop fonctionner si on utilise la méthode exp… On pourrait être malin et lui donner un second argument (un kk maximum) et dans ce cas, ça terminera, et ça donnera en fait un moyen de contrôler la précision de la méthode (mais on aura alors un code compliqué pour pas grand-chose).

PS : La flemme (celle de calculer la factorielle) explique la présence de Math.gamma



Aucun commentaire

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte