2011-11-27 5 views
6

J'ai essayé de faire défiler une liste et de l'écrire dans un fichier. Pourquoi ce qui suit ne fonctionne-t-il pas?Écrire dans un fichier (Prolog)

loop_through_list(List) :- 
    member(Element, List), 
    write(Element), 
    write(' '), 
    fail. 

write_list_to_file(Filename,List) :- 
    tell(Filename),  % open file to be written 
    loop_through_list(List), 
    told.    % flush buffer 
+1

Regardez dans le fichier que vous avez créé en exécutant 'write_list_to_file/2'! Tout à fait probablement il aura non seulement les éléments de la liste, mais aussi d'autres données non intentionnelles à la fin du fichier. Comme d'autres l'ont déjà remarqué, utiliser 'open/3' et' close/1' est beaucoup plus sûr. – false

+0

Je suis curieux de savoir où l'information sur le manque de fiabilité de dire et dit peut être trouvé, pouvez-vous me diriger vers la source? – chutsu

+1

Vous trouverez une explication [ici] (http://stackoverflow.com/questions/8269971/prolog-how-to-save-file-in-an-existing-file/8270091#8270091) – false

Répondre

7

D'abord, pourquoi il échoue:
Vous utilisez ne pas provoquer retours en arrière, ce qui peut être une bonne technique, mais pas là. Parce que cela rendra votre prédicat faux à la fin, quand le membre a manqué de solutions. Ensuite, une fois que loop_through_list est faux, dit n'est pas atteint et l'écriture n'est pas faite correctement (quand je le teste, le fichier est créé mais rien n'est écrit).
Si vous utilisez:

loop_through_list([]). 
loop_through_list([Head|Tail]) :- 
    write(Head), 
    write(' '), 
    loop_through_list(Tail). 

à la place, cela fonctionne. Mais, même avec ce code de travail, vous pouvez utiliser open (Filename, write, Stream), écrire (Stream, Element) et fermer (Stream) au lieu de dire et dit pour les raisons expliquées dans le lien au bas de cette réponse.
Par exemple:

loop_through_list(_File, []) :- !. 
loop_through_list(File, [Head|Tail]) :- 
    write(File, Head), 
    write(File, ' '), 
    loop_through_list(File, Tail). 

write_list_to_file(Filename,List) :- 
    open(Filename, write, File), 
    loop_through_list(File, List), 
    close(File). 

ou

loop_through_list(File, List) :- 
    member(Element, List), 
    write(File, Element), 
    write(File, ' '), 
    fail. 

write_list_to_file(Filename,List) :- 
    open(Filename, write, File), 
    \+ loop_through_list(File, List), 
    close(File). 

en utilisant votre code et astuce joel76.

Voir Prolog how to save file in an existing file
Il couvre la même matière.

+0

par ailleurs, ce qui est le '\ +'? cela ne signifie-t-il pas (par exemple, "!" en C). – chutsu

+1

@chutsu: oui, c'est le cas. Dans SWI-pl au moins (et d'autres peuvent vous parler d'autres implémentations), ** not/1 ** est obsolète et l'utilisation de ** \ +/1 ** est recommandée comme indiqué dans cette [page de manuel] (http : //www.swi-prolog.org/pldoc/doc_for? object = not/1) – m09

2

prédicat loop_through_list (Liste), échoue toujours, si vous succed suffit d'écrire \ + loop_through_list (Liste),

3

je ne vois pas la raison de ne pas utiliser cette méthode pour écrire un liste dans un fichier.
La programmation en prolog ne devrait généralement pas impliquer de boucles;
d'ailleurs, ce n'est pas une structure en boucle, c'est plus comme un hack (ou même abus).
(et tout comme votre cas conduit à des bogues et de problèmes inattendus)

Il suffit d'utiliser la récursivité et imprimer les éléments de la liste:

write_list([]). 
write_list([H|T]):- 
    write(H), 
    write(' '), 
    write_list(T). 

plus élégant et pourrait être plus efficace aussi. Autre que cela, en utilisant open/4 etc (ISO IO) au lieu de tell/1 etc (Edinburgh IO) est généralement mieux; vérifier false's post