La plupart du temps, Factor gère l'itération au moyen de combinateurs comme each, map et count. Parfois, cependant, la façon la plus élégante d'exprimer un calcul est la récursivité : un mot qui s'appelle lui-même.
Une définition : peut s'appeler elle-même directement :
: count-down ( n -- )
dup 0 = [ drop ] [ dup . 1 - count-down ] if ;
5 count-down
! prints 5 4 3 2 1
if-empty (dans sequences) est le cas de base naturel de la récursivité :
if-empty ( seq emptyquot nonemptyquot -- )
{ 4 0 9 } [ "empty" ] [ "got data" ] if-empty .
! => "got data"
emptyquot s'exécute avec la séquence (vide) déjà consommée ; nonemptyquot s'exécute avec la séquence encore sur la pile.
cond : une chaîne de branches gardéesQuand la récursivité comporte plus de deux cas, cond (dans combinators) garde le code lisible :
: classify ( n -- label )
{
{ [ dup 0 < ] [ drop "negative" ] }
{ [ dup 0 = ] [ drop "zero" ] }
[ drop "positive" ]
} cond ;
DEFER:
Une définition : peut s'appeler elle-même directement, mais quand deux mots s'appellent l'un l'autre, l'analyseur syntaxique voit le premier avant que le second n'existe. DEFER: réserve un nom pour que la première définition puisse se compiler :
DEFER: even?
: odd? ( n -- ? ) dup 0 = [ drop f ] [ 1 - even? ] if ;
: even? ( n -- ? ) dup 0 = [ drop t ] [ 1 - odd? ] if ;
DEFER: est aussi pratique quand un mot auxiliaire se lit plus naturellement après le mot qui l'utilise.
Tu tiens le compte quotidien du nombre d'oiseaux qui visitent ton jardin. Les données sont stockées dans un tableau d'entiers, avec le compte du jour en premier.
Définis today pour qu'elle récupère un tableau de comptes quotidiens depuis la pile et renvoie le compte du jour, ou f si le tableau est vide.
{ 2 5 1 } today .
! => 2
{ } today .
! => f
Définis increment-day-count pour qu'elle renvoie un nouveau tableau où le compte du jour est augmenté de un. Si l'entrée est vide, renvoie { 1 }.
{ 4 0 2 } increment-day-count .
! => { 5 0 2 }
{ } increment-day-count .
! => { 1 }
Définis has-day-without-birds? pour qu'elle renvoie t si au moins un jour a enregistré zéro oiseau, sinon f.
Utilise la récursion plutôt que any? ou d'autres mots de séquence d'ordre supérieur.
{ 2 0 4 } has-day-without-birds? . ! => t
{ 3 8 1 5 } has-day-without-birds? . ! => f
Définis total pour qu'elle renvoie la somme de tous les comptes.
Utilise la récursion plutôt que sum.
{ 4 0 9 0 5 } total .
! => 18
Un jour chargé est un jour avec cinq oiseaux ou plus. Définis busy-days pour qu'elle renvoie le nombre de jours chargés.
Utilise la récursion plutôt que count.
{ 4 5 0 0 6 } busy-days .
! => 2
Inscris-toi sur Exercism pour apprendre et maîtriser Factor avec 47 concepts163 exercices, et un vrai mentorat humain, le tout gratuitement.