2011-05-26 3 views
4

Disons que j'ai ces faits:Comment renvoyer une liste dans Prolog?

parent(bob, sam). %bob is sam's parent 
parent(sara, sam). %sara is sam's parent 

je voulais savoir qui étaient parents de Sam et les retourner dans une liste et en tant que telle utilisée:

list_parents(P, L) :- findall(Parent, parent(Parent, P), L). 

Ce que je veux à faire est maintenant poser la même question, mais avec un seul argument en tant que tel:

findParents(sam). 

J'ai essayé:

findParents(Name) :- list_parents(Name, L). 

mais de cette manière, Prolog répond simplement "True".

+1

Impossible. Ne fais pas ça. Prolog n'a pas de valeur de retour sauf les valeurs booléennes. –

Répondre

2

vous pouvez imprimer la liste si vous voulez que l'utilisateur de voir quelque chose comme:

findParents(Name):- 
    list_parents(Name,L), 
    print(L). 

mais ce isnt retourner exactement. rappelez-vous, en prologue, il n'y a pas de fonctions et donc pas de "valeurs de retour". vous pouvez simuler une fonction en écrivant foo (Args, Return) mais vous pouvez toujours l'appeler comme foo (X, sam) - parfois il donnera ce que vous voulez, parfois il ne va pas, parfois il va planter.

+0

C'est mon problème cependant. J'ai déjà programmé dans de nombreuses langues, mais je n'arrive pas à comprendre comment cela fonctionne. Je n'ai pas besoin de l'imprimer, j'ai besoin du même résultat que j'appellerais la fonction "list" de list_parents. – porlognewbie

+0

bien, il suffit d'appeler le prédicat list_parents avec la variable où vous voulez stocker la liste. comme list_parents (sam, liste). alors prolog va unifier la liste avec la liste des parents de sam. Si cela vous facilite la tâche, vous pouvez imaginer que c'est l'équivalent de List = list_parents (sam), mais ce n'est pas tout à fait vrai. –

5

La chose avec Prolog est que c'est un peu différent de la plupart des langues (euphémisme, s'il était tout un):

  • Toutes les variables sont scope localement.

  • Les valeurs de variables sont invariantes une fois liées (unifiées), à moins que le retour arrière ne les délie.

  • Les prédicats ne renvoient pas de valeur au sens conventionnel. Ils réussissent ou échouent. Pour récupérer la valeur du test d'un prédicat, vous évaluez le prédicat en lui transmettant quelque chose de votre prédicat. Peu importe si vous lui passez une variable ou une valeur liée: le prédicat appelé réussira ou évaluera si ce que l'appelant a unifie avec ce que vous lui avez passé. Si vous avez passé une variable et que le prédicat appelé l'unifie avec une valeur non variable, votre variable est liée à cette valeur. Pensez-y (un peu) comme si vous aviez un langage procédural où chaque fonction renvoyait bool et toutes les valeurs des paramètres étaient transmises par référence.

Qu'est-ce que vous avez essayé travaillé:

findParents(Name) :- list_parents(Name, L). 

La variable L a été unifiée avec (a été lié à) la liste renvoyée par findall/3. Et puis il est sorti de la portée.

Si vous voulez réellement faire quelque chose avec qui sont revenus (lié) valeur, vous devez y faire face où il est dans le champ, ou d'unifier cette valeur avec quelque chose que ce prédicat a été invoqué avec et passer ainsi en place la pile d'appels. Ou, vous pourriez l'affirmer dans la base de données des faits et l'enregistrer pour plus tard.

La façon dont prolog fonctionne est que le prédicat racine utilisé pour démarrer votre "programme" définit un arbre de recherche en termes de prédicats dans votre base de données.Le «moteur» de Prolog effectue ensuite une recherche en profondeur, de gauche à droite, de cet arbre. Votre prédicat réussit lorsque le moteur atteint un nœud feuille de l'arborescence de recherche que vous avez définie. Le retour en arrière dans votre prédicat amène le moteur à rechercher la solution suivante dans l'arborescence de recherche. Par conséquent, tout ce que vous voulez accomplir de manière persistante doit se produire en tant qu'effet secondaire du "moteur" prologue évaluant un prédicat. Par exemple print() réussit toujours juste une fois (quand vous entrez dans la boîte) ... et comme un effet secondaire imprime tout ce que vous lui avez demandé d'imprimer. Retour arrière dans l'impression ne pas "annuler" l'impression, mais print() ne réussit pas à nouveau.

2

La bibliothèque func fournit une syntaxe pour les fonctions avec des valeurs de retour dans SWI-Prolog. Dans cet exemple, vous pouvez imprimer tous les parents de sam en écrivant writeln(list_parents $ sam):

:- initialization(main). 
:- use_module(library(func)). 

main :- writeln(list_parents $ sam). 

list_parents(P, L) :- findall(Parent, parent(Parent, P), L). 
parent(bob, sam). %bob is sam's parent 
parent(sara, sam). %sara is sam's parent 

De même, vous pouvez définir une fonction avec plusieurs paramètres comme celui-ci:

% return a item at an index in a list. 
nth0((Index,List),ToReturn) :- 
    nth0(Index,List,ToReturn). 

... et puis l'utiliser comme ceci:

example :- 
    ListIndex = (nth0 $(0,[1,2,3,4])), %returns 1, which is the first item in this list 
    writeln(ListIndex).