web-dev-qa-db-fra.com

variables singleton dans prolog

Je testais ma nouvelle version du prologue SWI et je continue de rencontrer l'erreur: variable singleton.

Exemple:

member(X,[X|T]).

member(X,[X|T]) :- member(X,T).

recherche le membre d'une liste telle que:

member(yolands,[yolanda,tim])

X = yes

mais à la place, j'obtiens une erreur variables singleton pour X et T

si je fais ce qui suit:

member(X,[X|_]).
member(X,[_|T]) :- member(X,T).

Ça marche mais ça a l'air moche!

Quelqu'un peut-il expliquer pourquoi des variables uniques ne sont pas autorisées et si cette norme ANSI?

21
Timothy Lawman

Les variables singleton sont inutiles dans Prolog, et sont facilement introduites en modifiant les fautes de frappe.

Le avertissement est le bienvenu pour moi, car il permet de repérer facilement une cause d'erreur aussi fréquente.

Étant un avertissement, vous pouvez exécuter du code contenant des singletons, mais toute valeur que ceux-ci prendront éventuellement sera perdue.

Je ne pense pas que ISO standard (jamais entendu parler de ANSI ) interdit une telle variables.

Vous pouvez réécrire votre exemple de cette façon

member(X, [Y|T]) :- X = Y ; member(X, T).

puis oubliez le singleton.

15
CapelliC

Vous avez un bug ici:

member(X,[X|T]) :- member(X,T).

Ce que vous en fait dites (par opposition à ce que vous pensez que vous dites) est que member/2 Tient si X est en tête de la liste et = présent dans la queue de la liste. Ce prédicat ne sera vrai que pour les N premiers exemplaires de la même chose au début d'une liste, c'est donc une chose très étrange à dire!

?- member(X, [a,a,c]).
X = a ;
X = a ;
false.

?- member(X, [b,a,a]).
X = b ;
false.

Maintenant, vous pouvez corriger le bogue et toujours avoir un avertissement singleton en faisant quelque chose comme ceci:

member(X, [Y|T]) :- member(X, T).

Mais ce n'est ni aussi bon que la définition conventionnelle à deux têtes ou la version @ CapelliC (+1) avec un OU explicite. Je pense que vous devriez attendre de comprendre un peu mieux Prolog avant de mettre beaucoup de stock dans votre sens de l'esthétique du code Prolog. Si vous vous en tenez à cela pendant un certain temps, vous apprécierez cet avertissement ainsi que l'utilisation de variables anonymes.

Ce qui rend les variables singleton inutiles dans Prolog, c'est qu'elles sont nommées mais on ne sait rien à leur sujet et elles n'ont aucun effet sur le reste du calcul. Le soulignement souligne qu'absolument tout pourrait y entrer sans affecter le sens. Ce qui rend

member(X, [X|T]).

il est vrai que le X est la position 1 est le même que le X en tête de la liste en position 2. Les listes doivent être vides ou avoir une tête et une queue, mais ce qui est dans la queue n'est pas pertinent ici, ce qui compte est que X est aussi la tête. Le T pourrait être le reste de la liste, ou ce pourrait être une liste incorrecte, ou ce pourrait être une boîte à pain ou des éclairs ou l'odeur de l'air un jour de printemps. Cela n'a aucune incidence sur la vérité de member(X, [X|T]).

L'avertissement singleton vous dit "vous avez réservé un nom pour quelque chose ici, mais vous n'appelez jamais rien par ce nom". La première chose que je fais quand je reçois ce message et ce n'est pas une faute de frappe évidente est de remplacer le nom par _ et de voir si mon code a toujours du sens. Si ce n'est pas le cas, j'ai une erreur logique. Si c'est le cas, c'était probablement inutile.

10
Daniel Lyons

Vous pouvez en lire plus sur la page officielle de SWI-Prolog FAQ

Les cas les plus courants de cet avertissement apparaissent:

  1. Fautes d'orthographe dans les variables
  2. Oubliez d'utiliser/lier une variable

SWI suggère quelques façons de l'ignorer:

  1. Utilisez à cet effet une variable anonyme nommée _.
  2. Utilisez votre variable commençant par _ (comme _T, _X), Pour éviter les avertissements et documenter ce que vous ignorez.
  3. Si vous savez ce que vous faites, vous pouvez utiliser :- style_check(-singleton). et tous les avertissements devraient disparaître.
3
Olexiy Pyvovarov