Utilisation de (=..)/2
@TopologicalSort a déjà donné une belle réponse, en utilisant (=..)/2
pour convertir un terme en une liste de foncteur et d'arguments.
Cela résout évidemment le problème immédiat de manière très générale.
Cependant, cela présente également ses propres inconvénients : Tout d'abord et surtout, (=..)/2
n'est pas une relation générale. Par exemple, nous avons :
?- X =.. Y.
**ERREUR: Les arguments ne sont pas suffisamment instanciés**
Cela signifie que nous ne pouvons pas utiliser cette construction pour générer des solutions. Cela fonctionne uniquement si ses arguments sont suffisamment instanciés.
Deuxièmement, l'utilisation de (=..)/2
s'accompagne également d'un surcoût en temps et en mémoire pour construire et représenter une liste en plus du terme qui est déjà là sous une forme différente. (Et, mutatis mutandis, dans l'autre sens également bien sûr.)
Il peut donc être intéressant de se demander : Existe-t-il différentes manières de résoudre cette tâche ? Sont-elles mieux adaptées ?
Alternative 1 : Le faire manuellement
Comment te convertir ? Laisse-moi compter les moyens.
À partir de l'exemple que vous citez, nous devons être capables de gérer— dans l'ordre de leur apparition— des termes des formes suivantes :
Le point ici est que le nombre de cas montrés est fini, et donc nous pouvons facilement tous les gérer de cette façon :
atm\_list(atm(A), \[A\]).
atm\_list(atm(A,B), \[A,B\]).
atm\_list(atm(A,B,C), \[A,B,C\]).
atm\_list(atm(A,B,C,D), \[A,B,C,D\]).
Pour convertir une liste de tels termes, vous pouvez utiliser maplist/2
:
?- Ls = \[atm(abd,bubu,ha), atm(aei),atm(xyz,huhu), atm(aabb,a,e,x)\],
maplist(atm\_list, Ls, Lists).
Ls = \[atm(abd, bubu, ha), atm(aei), atm(xyz, huhu), atm(aabb, a, e, x)\],
**Lists = \[\[abd, bubu, ha\], \[aei\], \[xyz, huhu\], \[aabb, a, e, x\]\].**
Un avantage majeur est que cette relation est très générale et peut également être utilisée pour générer des réponses :
?- atm_list(A, Ls).
A = atm(_27464, _27466, _27468),
Ls = [_27464, _27466, _27468] ;
A = atm(_27464),
Ls = [_27464] ;
A = atm(_27464, _27466),
Ls = [_27464, _27466] ;
A = atm(_27464, _27466, _27468, _27470),
Ls = [_27464, _27466, _27468, _27470].
C'est également plus efficace que d'utiliser (=..)/2
. Clairement, cela ne peut être fait que si le nombre de cas émergents est fini. (Exercice : Écrivez un programme Prolog qui génère des clauses pour tous les entiers de 1 à N.)
Alternative 2 : Utiliser des listes
Il existe plusieurs critères bien connus pour juger si les listes sont une structure de données appropriée. Par exemple :
- L'liste vide a-t-elle un sens dans votre cas d'utilisation ?
- Y a-t-il des cas sensibles pour toutes les longueurs possibles ?
- Etc.
Seule vous pouvez répondre à cette question pour votre cas d'utilisation particulier, donc je montre seulement à quoi cela pourrait ressembler : Supposez que vous représentez toute votre liste initiale de la manière suivante :
\[\[abd,bubu,ha\],\[aei\],\[xyz,huhu\],\[aab,a,e,x\]\]
Alors, toute la question n'existe même pas, car les éléments sont déjà spécifiés en tant que listes. Ainsi, il n'y a plus besoin de convertir quoi que ce soit.