Comme il a déjà été dit, la relative proximité du modèle mathématique (les matrices) fait apparaître des symétries dans le programme.
On donne en annexe les fonctions de traitement (*put et *rem) et les fonctions auxiliaires (ascendance, *ins et *sup).
1. Les données
Les traitements *put et *rem sont inverses l'un de l'autre, par définition. On va donc encore assez logiquement observer une symétrie entre ces traitements – sur un même type de données PHYL ou OPER.
On donne ici aussi les deux fonctions où la similitude est la plus visible :
(de *putoper (nomoper attoper)
(let ((oper (makeoper nomoper attoper)))
(ins opert oper)
(mapv '(lambda (phyl)
(let ((drap (makedrap)))
(ins (operphyl phyl) drap)
(ins (phyloper oper) drap)))
phylt))
(*putoper-ana nomoper attoper))
(de *remoper (oper)
(let ((numoper (num opert oper)))
(numsup opert numoper)
(mapv '(lambda (phyl)
(numsup (operphyl phyl) numoper))
phylt))
(*remoper-ana oper))
Une écriture « plus orthodoxe » de *remoper serait :
(de *remoper (oper)
(sup opert oper)
(mapv '(lambda (phyl)
(sup (operphyl phyl) oper))
phylt))
(*remoper-ana oper))
qui rend le parallèle plus facile entre les deux fonctions – on remplace, subtilement, ins par sup ou réciproquement.
Les fonctions num... qui ont été introduites permettent d'améliorer l'efficacité de l'algorithme : au lieu de rechercher un élément de la liste d'après son nom, on retient son numéro d'ordre dans la liste (numoper), puis on accède directement à l'élément par ce numéro.
Pour garantir le passage de *remphyl à *remoper, il faut donc :
ins par sup,num, l'appel de la fonction
sup est « textuellement » remplacé par numsup, et le paramètre oper par numoper.On peut noter que dans ces manipulations « textuelles » du programme on est très loin du langage et de la sémantique des termes qu'il définit, et pourtant on est très près du sens intuitif qu'on donne au texte du programme.