Racket: première approche de lambda
Dans un article précédent, j’ai écrit une fonction Racket pour calculer les diviseurs d’un nombre n:
Puis on a vu comment faire des tests unitaires. Il est temps maintenant de faire un peu de refactoring.
Tout d’abord, le plus simple, on va extraire une fonction qui calcule un range de 1 à n inclus:
Vous noterez au passage que j’ai commencé à documenter mes fonctions en
spécifiant les types de données en entrée et en sortie. Vous remarquez aussi
que range-inclusive
ne fait pas partie de l’API du module:
(provide divisors)
.
Maintenant il nous faut extraire la fonction qui regarde si un nombre i est un diviseur de n:
Le nom de la fonction a changé au passage pour divisor-of?
. Mais surtout
nous avons du inclure n dans les arguments de la fonction.
On doit maintenant insérer cette fonction dans le code de la fonction
principale divisors
. Voici une première tentative un peu naive:
Évidemment ça ne marche pas, puisque Racket ne connait pas i, mais
ça nous donne une orientation. Pour que Racket sache ce que nous voulons
placer dans i, à savoir l’élément en cours de traitement par la fonction
filter
, on va passer par une fonction anonyme:
Une fonction anonyme (lambda) prend un argument (ou plusieurs) et une
expression. À chaque itération, filter
passe un élément tiré de
(range-inclusive n)
à la fonction anonyme (lambda (i) (divisors-of? n i))
.
Voilà donc notre module, après refactoring:
On aurait aussi pu écrire ce qui suit, à la place des trois fonctions ci-dessus:
Ça fait bien sûr beaucoup moins de code… Peut-être est-ce parceque je ne suis
pas encore habitué à Racket, mais je trouve aussi cela bien moins lisible.
Si on doit réutiliser les fonctions divisor-of?
et range-inclusive
, il
n’y a pas de question à se poser. Sinon…? Si vous connaissez bien
Racket/Scheme/Lisp laissez donc un commentaire pour me dire quelle version
est la plus idiomatique de ce type de langages.
À demain.