3 ms·
Eh, no, admittedly this is a bit confusing but the ";" at the top-level is not the same as the ;/2 disjunction operator. At the top-level the ";" is just a swit
by YeGoblynQueenne 5mo ago
Eh, no, admittedly this is a bit confusing but the ";" at the top-level is not the same as the ;/2 disjunction operator. At the top-level the ";" is just a switch to say "give me more". In most Prolog systems you can also press space for the same thing.
Whether a query will end with "false" or "true" really depends entirely on the query, and the predicates it's calling. So it depends on how a predicate is called. You just have to analyse the predicate in the good, old-fashioned way of eyballing it and maybe running it a couple of times to see why it fails or succeeds, and why it first succeeds and then fails like above.
This is really all down to determinism, which is to say, whether a predicate leaves behind a choice point or not. In this particular case, what's going on can be revealed by looking at the trace of the query. For the following, I loaded the Pokemon database from https://github.com/alexpetros/prologdex/blob/main/src/dex/pokemon.pl https://github.com/alexpetros/prologdex/blob/main/src/dex/po...) into SWI-Prolog and traced it like this:
[trace] 21 ?- type(Pokemon, water), type(Pokemon, ice).
Call: (15) dex:type(_2236, water) ? creep
Exit: (15) dex:type(squirtle, water) ? creep
Call: (15) dex:type(squirtle, ice) ? creep
Fail: (15) dex:type(squirtle, ice) ? creep
Redo: (15) dex:type(_2236, water) ? creep
Exit: (15) dex:type(wartortle, water) ? creep
Call: (15) dex:type(wartortle, ice) ? creep
Fail: (15) dex:type(wartortle, ice) ? abort
% Execution Aborted
Now, if you squint real hard you'll see that the Prolog engine first unifies the variable 'Pokemon' with the name of a Pokemon, "squirtle". That happens to be the first pokemon in the database that has "water" as the type. Basically the engine looks for a type/2 fact where the second argument is "water" and finds type('squirtle', 'water') first.
In the second call... I mean this one:
Call: (15) dex:type(squirtle, ice) ? creep
The engine looks for a fact that would satisfy the second goal in the top-level query. This is the top-level query:
[trace] 21 ?- type(Pokemon, water), type(Pokemon, ice).
And this is the second goal in it:
type(Pokemon, ice)
Since "Pokemon" is already bound to "squirtle", the engine tries to satisfy the fact
type(squirtle, ice)
It can't, so it fails. And then it repeats with the second water pokemon in the list, which is wartotrtle.
What happens when the engine finds a pokemon that is both water and ice? The first one in the database is dewogong, at which point the tracer goes like this:
Redo: (15) dex:type(_92, water) ? creep
Exit: (15) dex:type(dewgong, water) ? creep
Call: (15) dex:type(dewgong, ice) ? creep
Exit: (15) dex:type(dewgong, ice) ? creep
Pokemon = dewgong .
So this time both goals in the top-level query are satisfiable and the engine returns the name of the value of "Pokemon" that makes the query true (well, satisfiable).
At that point the "." means I pressed "enter" and that's basically saying "no more thank you". I was getting a little impatient. If I had pressed ";" (or space) instead, we'd have a repeat of the previous pattern with successive failures until another water and ice pokemon was found. The next one in the database is cloyster, and so it goes.
That back-and-forth between success and failure goes on until we run out of pokemon. At some point the engine can't unify either goal of the top-level query with a fact in the database so the final result is "false"; because after succeeding a bunch of times, it can't succeed no more.
Honestly this is a fair question to have and I had to trace the query to be able to give a fair account of it so the advice to take it as "expected" is not that bad. Prolog is doing something mind-numbingly repetitive on the background and it's hard to follow it, so sometimes the best thing is to just run your program and see what it does, instead of trying to intuit it.
- jodrellblank 5mo ago> "but the ";" at the top-level is not the same as the ;/2 disjunction operator. At the top-level the ";" is just a switch to say "give me more"." I understand that's the experience of using it, but I mean if I open the SWI Prolog toplevel and query: ?- X = 1 ; X = 2. Then press space, I get: X = 1 ; X = 2. which is exactly the same Prolog term, two unifications, each is a solution to the query, a disjunction between them, terminated with a full stop. Is that really not the same semicolon usage/meaning/semantics in the query as in the answers?
- deleted 5mo ago[deleted]
- YeGoblynQueenne 5mo agoIn that case, your query is a disjunction but suppose you had a set of clauses like this: fruit(apples). fruit(oranges). fruit(bananas). likes(sam,X):- fruit(X). And then entered a query like this: ?- likes(sam,X). And got results like this: X = apples ; X = oranges ; X = bananas. Are those the results of a disjunction? I think it's clear that not: our rule says that "sam likes X if X is a fruit, for all X"; "for all" because in Prolog every variable is implicitly universally quantified. So the interpretation of the results of the query is: sam likes apples AND sam likes oranges AND sam likes bananas Not: sam likes apples OR sam likes oranges OR sam likes bananas Sam likes all the fruit! The different values of X are not disjuncts, they're conjuncts. All that'll probably get me lynched because it flies in the face of a lot of fudging perpetrated by Prolog courses and even some textbooks that should know better, and that tell you that e.g. a set of rules is like an if-then-else and that when you get more results at the top-level those are alternatives. That's just wrong and I don't know why people teach Prolog like this, all it does is confuse students and make them hate Prolog more, but the formal definition of a logic program is that it's a conjunction of definite program clauses; where a definite program clause is a ... clause, therefore a disjunction. So a logic program is a conjunction of disjunctions, i.e. basically a formula in conjunctive normal form. So the ";" that appears automatically at the end of your query when you press space is not an "OR", otherwise it wouldn't appear when the results of the query are the members of a conjunction. What is it then? Try this. Instead of pressing ";" after the first result of your query (after the X = 1) press "h" for "help". On SWI-Prolog you'll get this menu: ?- X = 1 ; X = 2. X = 1 Possible actions: ; (n,r,space,TAB): redo | t: trace&redo *: show choicepoint | . (c,a,RET): stop w: write | p: print +: max_depth*5 | -: max_depth//5 b: break | h (?): help Action? Thus finally* revealing the meaning of ";" at the top-level: it instructs the listener (i.e. the Prolog REPL) to enter the redo port. The ";" at the top-level means "redo" not "OR". And that's true even in your query which is explicitly formulated as a disjunction. With an ";". It's confusing. _______________ * I know, sorry.