.how to write single quote( ' ) in write predicate in Prolog? - prolog

I want to add short info in the beginning of the program and i goes like this
message :-
nl,nl,
write(' To start type '), nl,
write(' ?- solve(Input1,Input2,Output3) '), nl.
:- message.
And this is fine...but i need write(' ?- solve('Input1','Input2',Output3) '), nl
so when i run the program it should print
To start type
?- solve(' Input1 ' ,' Input2 ' ,Output3 )
thanks in advance :)

Escape the quote with backslash.
For example, to output a single single-quote:
?- write('\'').
'
true.
As a general rule, you should of course avoid side-effects entirely. A good solution is to describe the output using a DCG. This makes it amenable to test cases, which are hard to write if output only appears on the terminal.
write/1 is particularly rarely used. If you really need to output something, use format/2. This sounds scary if you know DOS, but it really isn't.
An important advantage of format/2 is that it lets you conveniently mesh static text with flexible arguments, for example:
?- member(X, [friend,foe,love]),
format("hello my '~q'!\n", [X]),
false.
Yielding:
hello my 'friend'!
hello my 'foe'!
hello my 'love'!
Note that the issue of single quotes didn't even arise in this case. The analogous issue with " can again be solved by using \:
?- format("a \"test\"", []).
a "test"

Related

Prolog - program skipping over read?

Title more or less says it all. I got the following code in SWI-PROLOG:
get_card(1):-
nb_getval(playerOneHand, Hand),
write("Select which cards you want to play:"), nl,
read(Input),
handle_input(Input).
get_card(2):-
nb_getval(playerTwoHand, Hand),
write("Select which cards you want to play:"), nl,
read(Input),
handle_input(Input).
Expected input-format right now is something like [ 0, 1 ]. to play your first two cards, [ 0 ]. to only play your first card, so on and so forth. While I know this is beyond horrible as far as input formats go, the priority right now is to atleast get it working, then move on to a better UI from there.
This is what happens:
I'm very new to Prolog so bear with me, but this is how I'm looking at it: It seems to be "skipping" over our read and is now expecting a new command to be entered instead (ENTER has been pressed in the above picture).
I feel like the solution should be very simple but unfortunately is nothing I can seem to wrap my head around. Thanks in advance!
EDIT: Example code that can be ran to reproduce the issue, unless it's only happening on my system for some reason:
% Initialize globals
?- nb_setval(playerOneHand, []).
?- nb_setval(playerTwoHand, []).
handle_input(Input, Hand):-
write("Input is "), write(Input), nl,
write("Hand is "), write(Hand), nl.
get_card(1):-
nb_getval(playerOneHand, Hand),
write("Select which cards you want to play: "), nl,
read(Input),
handle_input(Input, Hand).
get_card(2):-
nb_getval(playerTwoHand, Hand),
write("Select which cards you want to play: "), nl,
read(Input),
handle_input(Input, Hand).
?- write("Player 1: "), get_card(1), nl,
write("Player 2: "), get_card(2), nl.
Using SWI-Prolog and the given code in a test.pl file, it is simply consulted via the terminal interface (File -> Consult -> test.pl). Trying to give SWI-Prolog ANY kind of input then results in the issue at hand.
As mentioned by Isabelle Newbie in the comments, swipl.exe (that is started by default) has a long-running bug associated with proper input/output. Navigating to where Prolog is installed and instead using swipl-win.exe seems to have done the trick.

Prolog read predicate cant read user key in in initialization?

I want to have a prolog program which can auto run once I compile finish and it should read input from user keyboard. However when i use
:- write('Your name is: '), nl, read(X).
there is not any effect on read(X), which it means that there us not any prompt for users to key in. Is there any solution for this problem? My prolog compiler is WIN-Prolog 5.0, thanks for your helo :)
maybe you need something like
:- initialization(main). % changed to be ISO compliant, was :- initialization main.
main :- write('Your name is: '), nl, read(X).
at least, ISO Prologs do it in this way....
Since read/1 is meant to parse Prolog (it's a full fledged parser), you must supply a Prolog term, and don't forget, as Joel76 suggested, to complete input with a dot: for instance:
Your name is:
|: 'Carlo'.

Undefined procedure in SWI-Prolog

Ok i got these two predicated hangman and graphics
fail([]).
hangman:-
getPhrase(Ans),
!,
write('Welcome to hangman.'),
nl,
fail(FailedList),
graphics(FailedList), %<--- The call is made here.
name(Ans,AnsList),
makeBlanks(AnsList, BlankList),
getGuess(AnsList,BlankList, FailedList).
graphics(FailedList):-
length(FailedList, L),
L == 0,
write('-----------'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('/\'), nl.
Why do i get the error: ERROR: hangman/0: Undefined procedure: graphics/1?
Note that if i put the predicate graphics inside hangman in comments my program works fine.
(this answer is not really about the question asked so please let the answer to #SeçkinSavaşçı who did a great job answering the question, it's more of a code review)
Here, you visibly want to test if a list is empty and react accordingly by displaying some things. For the test if a list is empty part, you're doing it wrong:
graphics(FailedList):-
length(FailedList, L),
L == 0,
% some IO stuff
In prolog, you can use unification in a more straightforward manner:
graphics(FailedList):-
length(FailedList, 0),
% some IO stuff
or, better, where you directly test for the empty list in the head as a condition to execute the body of the predicate:
graphics([]):-
% some IO stuff
For the IO part, you're doing it kinda wrong again. SWI-Prolog, for example, has a writeln/1 predicate, that would make your code lighter:
graphics([]):-
writeln('-----------'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('/\\').
Still better, the format/1 predicate could be used:
graphics([]):-
format('-----------~n|~18~n|~n|~n|~n|~n|~n|~n|~n/\\').
The main predicate seems to have some problems too, but I'll let you look into it and ask questions if you're stuck somewhere :)
write('/\'), nl.
In the last line, you are escaping the ending quotation mark with \'. Change it to:
write('/\\'), nl.
BTW: #Mog has written the answer before I had a look at the comments, I tested it and now it finds graphics/1.

Writing to file (Prolog)

I've been trying to loop through a list and writing it to a file, why is the following not working?
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
First, why it fails :
You use fail to provoke backtracking, which can be a good technique, but not there. Because it will make your predicate false in the end, when member has ran out of solutions. Then, once loop_through_list is false, told isn't reached and the writing isn't made properly (when I test it, the file is created but nothing is written).
If you use :
loop_through_list([]).
loop_through_list([Head|Tail]) :-
write(Head),
write(' '),
loop_through_list(Tail).
instead, it works.
But, even with this code working, you might want to use
open(Filename, write, Stream), write(Stream, Element) and close(Stream) instead of tell and told for the reasons explained in the link at the bottom of this answer.
For example :
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).
or
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).
using your code and joel76 trick.
See Prolog how to save file in an existing file
It covers the same matter.
I fail to see the reason to do use this method to write a list to a file.
Programming in prolog should generally not involve loops;
besides, this is not a loop structure, it's more like a hack (or even abuse).
(and just like your case leads to unexpected bugs and problems)
Just use recursion and print the elements of the list:
write_list([]).
write_list([H|T]):-
write(H),
write(' '),
write_list(T).
more elegant and could be more efficient too.
other than that, using open/4 etc (ISO IO) instead of tell/1 etc (Edinburgh IO) is generally better; check false's post
predicate loop_through_list(List), always fails, so to succed you just have to write \+loop_through_list(List),

Prolog print statement does not work as expected

I was trying to define a functor and print each individual items of list in Prolog, but Prolog is not printing in correct format.
rint(L):-
write(H).
the output is like
rint([a, s,v ,c]).
_L139
true.
This is what I expect to achieve by calling the functor, any help or thought is appreciated, I'm new to Prolog and learning it.
?- rint([a,b,c,d]).
.(a, .(b, .(c, .(d, []))))
I think it should be
rint(L) :- write(L).
Also if you want .(a, .(b, .(c, .(d, [])))) and not [a, b, c, d] in output, use display:
rint(L) :- display(L).
The problem is an error in your rule for rint.
Your definition says that rint(L) succeeds if write(H) succeeds. At that point, the interpreter knows nothing about H. So it writes a value it doesn't know, which is why you see the _L139, the internal representation of an uninitialised variable.
Having done that, write(H) has succeed, is true, so rint(L) is true. The interpreter tells you that: true.
To define your own rint/1 without relying on built-ins such as display/1, you would need to do something like
rint([]) :-
write([]).
rint([H|T]) :-
write('.('),
write(H),
write(', '),
rint(T),
write(')').
If you're trying to display an empty list, just write it. If you're trying to display any other list, write the opening period and parenthesis, write the Head, write the following comma and space, then call itself for the Tail of the list, then write the closing parenthesis.

Resources