I am currently delving into Prolog but coming from a JavaScript background a lot seems strange. For instance, I have a definition such as this:
np # Subject,
pp # IObject ; np # IObject,
However, in executing the result is not as expected. But when using parantheses it is.
np # Subject,
(pp # IObject ; np # IObject),
This seems strange to me, because , is a seperator so parantheses wouldn't be necessary. What is it exactly that parantheses do in Prolog. Please keep in mind that I am very new to Prolog.
, has a lower precedence value than ;. What this means in Prolog, is that an expression like
X ; Y , Z
is interpreted as
X ; (Y , Z)
To group them the other way around, you have to use parenthesis:
(X ; Y) , Z
Related
my(Selected_action,S,Result1):-
Selected_action = move(X,Y),
atomics_to_string([X, ",", Y], '', Tuple),
atomics_to_string(["move(", Tuple, ")"], '', Action),
atomics_to_string([Action, "scores", S], ' ', Result).
So when running the code like this:
?- my(move(3,4),5,X).
X = "move(3,4) scores 5".
But what I want is:
X = move(3,4) scores 5.
Note that the code you posted does not behave in the way you said; you have singleton variables Result1 and Result that should be the same.
As for your question, Prolog has (in a sense) two forms of providing "output". One is through the answer substitutions (the equations) that you see in the interactive shell. The idea of these substitutions is to give you equations that are syntactically valid Prolog fragments. But the version you ask for, X = move(3,4) scores 5. is not syntactically valid Prolog.
This form of output through answer substitutions is useful for programmers, but not necessarily for end users or for other tools that try to parse your program's output. The other form of output is therefore the printing of things to the terminal or to files, like the print functions of many other programming languages. In Prolog, you can do this, for example:
run_my(Query, Score) :-
my(Query, Score, Result),
format('~s~n', [Result]).
Which will hide the intermediate Result and just print the string without quotes:
?- run_my(move(3, 4), 5).
move(3,4) scores 5
true.
I implemented this predicate as a wrapper around your existing definition of my/3, which remains unchanged. This is the recommended approach: Do not mix terminal output with the essence of your computation, only add it in special wrappers.
You can use the op functionality of prolog like this...
program
([user]) .
:- op( 10'1 , 'xfy' , 'scores' ) .
my(SELECTED_ACTION,SCORE,RESULT)
:-
(
SELECTED_ACTION = move(X,Y) ,
RESULT = SELECTED_ACTION scores SCORE
) .
%^D
example usage
?-
my(move(3,4),5,X)
.
%# X = move(3,4) scores 5
alternate program
An alternate version shows the difference between an xfy op and a yfx op.
The x represents the domain and/\or the source.
The y represents the codomain and/\or the target.
Terminology from https://en.wikipedia.org/wiki/Morphism#Definition.
...
([user]) .
:- op( 10'1 , 'yfx' , 'scoreof' ) .
my(SELECTED_ACTION,SCORE,RESULT)
:-
(
SELECTED_ACTION = move(X,Y) ,
RESULT = SCORE scoreof SELECTED_ACTION
) .
%^D
alternate example usage
?-
my(move(3,4),5,X)
.
#% X = 5 scoreof move(3,4)
I am developing a predicate in Prolog and it is possible for it to terminate before the end of it.
For that reason I was looking for a command similar to return; (C++). I used a cut ! but I'm doubtful as to what it literally stands for and if it does exactly what return; does. Ex:
pred(X) :-
X = 1 -> do this, !; else do that,
write('x =/= 1').
void pred(int X) {
if (X = 1) {do this; return;} else do that;
cout << "x =/= 1";
}
Are the functions above exactly the same?
There is no direct correspondence of Prolog's execution mechanism and those of traditional imperative languages. So any analogy rather leads you on a dead path.
In your example, the cut has no effect whatsoever: The (->)/2 alone will already exclude the Else branch. In a sense it does a "tiny" cut on If and the alternative. Would there be another clause to pred/1, your cut would exclude that branch too.
Prolog's execution mechanism is much more complex. If you insist on an analogy in imperative languages, think of iterators. The cut causes all iterators in scope of the cut to produce a done on the next next. So it is a bit like a break. Somewhat. But only in a language that supports iterators in the first place.
If you want to learn Prolog, don't try to develop your notions out of these (half) broken analogies.
Better start by imagining what relations a Prolog predicate describes and approximate from that the meaning of a predicate. Procedural notions will fit in, one by one.
So you have some procedural code like this:
def foo():
if cond1:
handle_cond1()
return
if cond2:
handle_cond2()
return
do_other_stuff()
You can transform this in the procedural domain to have no explicit returns, first doing this:
def foo():
if cond1:
handle_cond1()
return
if cond2:
handle_cond2()
else:
do_other_stuff()
And then doing this:
def foo():
if cond1:
handle_cond1()
else:
if cond2:
handle_cond2()
else:
do_other_stuff()
Once you have eliminated the return statements you can transform this into Prolog:
foo :-
cond1 ->
handle_cond1
; (cond2 ->
handle_cond2
; do_other_stuff
).
There is no way to immediately succeed in Prolog. (You can immediately fail with fail). You will have to perform a transformation like this to achieve a similar flow. Best of all would be to follow #false's advice and learn Prolog on its own terms.
As was pointed out, Prolog doesn't map well to procedural thought.
I find the best way to think of a Prolog program and its "database" as a tree (forest?). The analogy is a bit rough since the graph contains cycles (recursion).
When you ask the prolog engine to determine the truth or falseness of a particular assertion (predicate), it commences to do a depth-first, left-to-right traversal of the tree using unification (pattern matching) to guide the traversal. When the traversal reaches a leaf node, the predicate is true. On backtracking, it... backtracks and continues the tree walk. When there are no more reachable leaf nodes, the predicate fails.
Prolog is a descriptive language: you describe the conditions for success in terms of predicate calculus. Then you simply let Prolog's inference engine find the applicable solutions. If you try to shoehorn procedural, imperative thought into the model, in addition to making things more difficult than they should otherwise be, in my experience, you're pretty much guaranteeing poor performance.
I found Leon Sterling and Eliot Shapiro's textbook, The Art of Prolog, to be invaluable and far more instructive and enlightening than Clocksin & Mellish's Programming in Prolog.
Edited to note: Your sample predicate
pred(X) :-
X = 1 -> do this , ! ; else do that ,
write('x =/= 1')
.
has some problems.
First, just like C or C# or other procedural languages where the and and or operators have different precedences so an expression like if ( a && b || c && d ) ... probably doesn't bind the way you think it does, due to operator precedence, your example predicate is probably not doing what you think it's doing: as written, it binds as
pred(X) :-
X=1 ->
( do_this , ! )
;
( do_that , write( 'x =/= 1' ) )
.
When what you probably wanted was
pred(X) :-
( X=1 ->
( do_this , ! )
;
do_that ,
) ,
write( 'x =/= 1' )
.
You need to use parentheses to omake your intended binding explicit:
pred(X) :-
( X=1 ->
( do_this , ! )
;
do_that
),
write('x =/= 1')
.
Further, the cut (!) in your example is unnecessary, since the implication operator -> acts as if there were a cut involved. This:
foo(X) :-
truthy(X) ->
writeln('truthy!')
;
writeln('falsy')
.
is pretty much exactly the same thing as
foo(X) :- truthy(X) , ! ,
writeln( 'truthy' ) .
foo(_) :- writeln( 'falsy' ) .
Third, you should make use of unification and pattern matching in the head. Ignoring the write/1, your example might make better sense as
pred(1) :- do_this , ! .
pred(X) :- do_that .
And in general, if you're learning prolog, I would say avoid the implication operator (and alternation (logical OR, ';'/2) in general. Prefer explicit predicates with multiple clauses to express choice. Instead of something like
foo(X) :- ( try_this(X) ; try_that(X) ; finally(X) ) .
prefer
foo(X) :- try_this(X) .
foo(X) :- try_that(X) .
foo(X) :- finally(X) .
And instead of implication:
foo(X) :- X=1 -> try_this(X) ; try_that(X) .
prefer something like this:
foo(1) :- ! , try_this(X) .
foo(X) :- try_that(X) .
I think it makes it easier to grok what's going on since it makes the choice points (and their elimination) explicit.
I would like to add that having solid coding guidelines can also help quite a bit to increase code readability and to avoid code brittleness.
Starting with #DanielLyons' code:
foo :-
cond1 ->
handle_cond1
; (cond2 ->
handle_cond2
; do_other_stuff
).
In practice, cascades of multiple nested if-then-else constructs occur: "if-then-elseif-then-elseif-then-elseif-then-...-else".
To increase readability, the code layout can be brushed up and the level of indentation adjusted:
foo :-
( cond1 -> handle_cond1
; cond2 -> handle_cond2
; do_other_stuff
).
Whenever code lines get too wide, a slightly less wide and more tall style may be preferable:
foo :-
( cond1
-> handle_cond1
; cond2
-> handle_cond2
; do_other_stuff
).
This is a simple mini program I have here that simplifies addition expressions that are queried. I can't seem to figure out how to finish it off. When I query the following:
sim(sum(sum(x,1),5),Val,[x:X]).
My result is Val = X+1+5. I would like it to simplify all the way to X+6.
Here is the code:
sim(Var, Value, Lst) :- member(Var:Value, Lst).
sim(Num, Num, _) :- number(Num).
sim(sum(Left, Right), Value, Lst) :-
sim(Left, LeftVal, Lst),
sim(Right, RightVal, Lst),
so(Value,LeftVal,RightVal).
so(Result, X, Y) :-
number(X),
number(Y), !,
Result is X + Y.
so(Result, X, Y) :- // debugging so(Result,_,Y) :-
Result = X + Y. // Y value write(Y), Result = Y.
What I do know is that my program is trying to simplify X+1 before adding X+1 and 5. When I change the last line of my "so" method to only give Y to Result I get Val = 6. Before that line I write Y to the screen for debugging purposes and it gives me 1 5 because of the recursion. Which means X must be a var? Is there a corner case not here that will allow me to simplify addition all the way down?
What I am noticing is that "so" never adds 1 and 5 because they are never arguments together in the "so" method that checks for X and Y to be numbers. X and 1 are the first arguments, then upon recursion X+1 and 5 are the arguments and it doesn't execute because number(X) fails when X is X+1
Expanding on my comment above: here is an example of an expression simplifier that separates 'symbols' from 'values' using two lists.
Notice how it uses the fact, in parsing and unparsing, that the only operator joining symbols and values is +.
I have written this little program:
married(guy1, fem1).
married(guy2, fem2).
married_to(X,Y):-!, married(X,Y); married(Y,X).
Prints:
X = guy1,
Y = fem1 ;
X = guy2,
Y = fem2.
My purpose was to print the married couples but one time each. The above rule works for me, but I can't understand why! How does this work?
What's the difference with that:
married_to(X,Y):- married(X,Y); married(Y,X).
This prints:
X = guy1,
Y = fem1 ;
X = guy2,
Y = fem2 ;
X = fem1,
Y = guy1 ;
X = fem2,
Y = guy2.
The cut commits execution to the first branch on the disjunction. Thus your rule:
married_to(X,Y):-!, married(X,Y); married(Y,X).
is operationally the same as:
married_to(X,Y):-!, married(X,Y).
And, given that there are no other clauses for the married_to /2 predicate, equivalent to:
married_to(X,Y):- married(X,Y).
imagine you have the equivalent definition married_to(X,Y):- true, !, married(X,Y) ; married(Y,X).. If true were to fail, then we'd jump to the alternative, but since it's not going to, we're firmly on the consequent branch (of the disjunction).
IOW your code is
married_to(X,Y):- ( !, married(X,Y) ) ; ( married(Y,X) ).
and not
married_to(X,Y):- !, ( married(X,Y) ; married(Y,X) ).
It is actually equivalent to
married_to(X,Y):- !, married(X,Y).
married_to(X,Y):- married(Y,X).
Perhaps with this it is easier to get a "feeling" for what is going on here. Obviously, the second clause of the predicate is cut off. :) We're committed to the first clause, the second doesn't get a chance to work at all.
What is the uppercase 'N' before prolog term mean?
such as the P in imp becomes NP in not?
imp(P,Q,Y) :- not(P,NP),or(NP,Q,Y).
NP means negation of P in prolog?
N is a kind of built in function in prolog?
Thanks a lot.
It has no special meaning. The term NP, which starts with an upper case, means that it is a variable (it could start with any upper case letter).
The way I read your procedure:
imp(P,Q,Y) :- not(P,NP),or(NP,Q,Y).
it means: ' to get P implies Q onto variable Y' we call procedure not/2 to get the negation of input P, and then we call procedure or/3 which computes "not P or Q" onto variable Y. Of course you have somewhere defined procedures not/2 and or/3