What does +,+ mode in Prolog mean? - prolog

So am being told a specific predicate has to work in +,+ mode. What does that mean in Prolog?

When one wants to give information on a predicate in prolog, those conventions are often used :
arity : predicate/3 means predicate takes 3 arguments.
parameters : predicate(+Element, +List, -Result) means that Element and List should not be free variables and that Result should be a free variable for the predicate to work properly. ? is used when it can be both, # is mentionned on the above answer but is not really used as much (at least in swi-pl doc) and means that the input will not be bound during the call.
so telling that somepredicate works in +, + mode is a shortcut for telling that :
% somepredicate/2 : somepredicate(+Input1, +Input2)

In order to give you a definite answer you need to tell us more than just +,+. For predicates whose arguments are only atoms, things are well defined: p(+,+) means that the predicate should only be called with both arguments being atoms.
But if we have, say lists, things are more complex. There are two meanings in that case. Consider member/2 which succeeds for member(2,[1,2,3]).
Are the queries member(2,[X]) or member(2,[X|Xs]) now +,+ or not?
The direct interpretation which is also used in ISO Prolog says that (quoting 8.1.2.2 Mode of an argument, from ISO/IEC 13211-1:1995):
+ the argument shall be instantiated,
In that sense both queries above are +,+.
However, there is another interpretation which implicitly assumes that we have access to the definition of the predicate. This interpretation stems from the mode declarations of DEC-10 Prolog, one of the first Prolog systems. So lets look at member/2:
member(X, [X|_]).
member(X, [_|Xs]) :-
member(X, Xs).
A mode member(+,+) would now mean that when executing a goal, this mode will hold for all subgoals. That is, member(2,[X]) would be +,+ whereas member(2,[X|Xs]) is not
because of its subgoal member(2,Xs).
People do confuse these notions quite frequently. So when you are talking about lists or other compound terms, it helps to ask what is meant.
For more on modes see this answer.

It means that the arguments to the predicate will both be input arguments (though not pure input).
This page has a succint description of all of Prolog's call modes.

Related

functor vs predicate - definition for students

The question of the difference between a functor and a predicate in prolog is asked often.
I am trying to develop an informal definition that is suitable for new students.
A functor is the name of a predicate. The word functor is used when
discussing syntax, such as arity, affix type, and relative priority
over other functors. The word predicate is used when discussing
logical and procedural meaning.
This looks "good enough" to me.
Question: Is it good enough, or is it fundamentally flawed?
To be clear, I am aiming to develop a useful intuition, not write legalistic text for an ISO standard!
The definition in https://www.swi-prolog.org/pldoc/man?section=glossary is:
"functor: Combination of name and arity of a compound term. The term foo(a,b,c) is said to be a term belonging to the functor foo/3." This does not help a lot, and certainly doesn't explain the difference from a predicate, which is defined: "Collection of clauses with the same functor (name/arity). If a goal is proved, the system looks for a predicate with the same functor, then uses indexing to select candidate clauses and then tries these clauses one-by-one. See also backtracking.".
One of the things that often confuses students is that foo(a) could be a term, a goal, or a clause head, depending on the context.
One way to think about term versus predicate/goal is to treat call/1 as if it is implemented by an "infinite" number of clauses that look like this:
call(foo(X)) :- foo(X).
call(foo(X,Y)) :- foo(X,Y).
call(bar(X)) :- bar(X).
etc.
This is why you can pass around at term (which is just data) but treat it as a "goal". So, in Prolog there's no need to have a special "closure" or "thunk" or "predicate" data type - everything can be treated as just data and can be executed by use of the call/1 predicate.
(There are also variations on "call", such as call/2, which can be defined as:
call(foo, X) :- foo(X).
call(foo(X), Y) :- foo(X, Y).
etc.)
This can be used to implement "meta-predicates", such as maplist/2, which takes a list and applies a predicate to each element:
?- maplist(writeln, [one,two,three]).
one
two
three
where a naïve implementation of maplist/2 is (the actual implementation is a bit more complicated, for efficiency):
maplist(_Goal, []).
maplist(Goal, [X|Xs]) :-
call(Goal, X),
maplist(Goal, Xs).
The answer by Peter Ludemann is already very good. I want to address the following from your question:
To be clear, I am aiming to develop a useful intuition, not write legalistic text for an ISO standard!
If you want to develop intuition, don't bother writing definitions. Definitions end up being written in legalese or are useless as definitions. This is why we sometimes explain by describing how the machine will behave, this is supposedly well-defined, while any statement written in natural language is by definition ambiguous. It is interpreted by a human brain, and you have no idea what is in this brain when it interprets it. As a defense, you end up using legalese to write definitions in natural language.
You can give examples, which will leave some impression and probably develop intuition.
"The Prolog compound term a(b, c) can be described by the functor a/2. Here, a is the term name, and 2 is its arity".
"The functor foo/3 describes any term with a name foo and three arguments."
"Atomic terms by definition have arity 0: for example atoms or numbers. The atom a belongs to the functor a/0."
"You can define two predicates with the same name, as long as they have a different number of arguments."
There is also the possibility of confusion because some system predicates that allow introspection might take either a functor or the head of the predicate they work on. For example, abolish/1 takes a functor, while retractall/1 takes the predicate head.....

What does the 'line' predicate mean in Prolog?

I am currently trying to understand some Prolog code for a game, but I somehow can't find any documentation about a specific predicate or rule that the programmer used, called 'line'.
He uses it in the argument list of other predicates, but neither is it customly defined by him nor can I find it in any documentation or anywhere else on the internet. I can't even call it seperately in my Prolog interpreter, even though it works perfectly in his code.
Can anyone tell me, what this predicate means or does?
solve([line(_, Line, Constr)|Rest]) :-
(specifically the line(_, Line, Constr) part)
This isn't a predicate, this is a data structure, in Prolog terminology, a compound term. Check out this glossary: https://www.swi-prolog.org/pldoc/man?section=glossary.
You probably have a list of lines, and each line is represented as a triple of values. Based on what you show it is a bit difficult to guess what exactly it contains. The _ in the first argument is the way the programmer says "I don't care about this value".
A compound term is the only non-atomic data structure in Prolog. A list for example is a nested compound term like .(a, .(b, .(c, []))) but the language has built-in functionality to let you write this as [a, b, c].
You can think of compound terms, with their names and arity, as the typed objects of Prolog (but please don't push this analogy too far).

Why doesn't maplist/3 use a template?

The maplist/3 predicate has the following form
maplist(:Goal, ?List1, ?List2)
However the very similar function findall/3 has the form
findall(+Template, :Goal, -Bag)
Not only does it have a goal but a template as well. I've found this template to be quite useful in a number of places and began to wonder why maplist/3 doesn't have one.
Why doesn't maplist/3 have a template argument while findall/3 does? What is the salient difference between these predicates?
Templates as in findall/3, setof/3, and bagof/3 are an attempt to simulate proper quantifications with Prolog's variables. Most of the time (and here in all three cases) they involve explicit copying of those terms within the template.
For maplist/3 such mechanisms are not always necessary since the actual quantification is here about the lists' elements only. Commonly, no further modification happens. Instead of using templates, the first argument of maplist/3 is an incomplete goal that lacks two further arguments.
maplist(Goal_2, Xs, Ys).
If you insist, you can get exactly your template version using library(lambda):
templmaplist(Template1, Template2, Goal_0, Xs, Ys) :-
maplist(\Template1^Template2^Goal_0, Xs, Ys).
(Note that I avoid calling this maplist/5, since this is already defined with another meaning)
In general, I rather avoid making "my own templates" since this leads so easily to misunderstandings (already between me and me): The arguments are not the pure relational arguments one is usually expecting. By using (\)/1 instead, the local variables are somewhat better handled and more visible as being special.
... ah, and there is another good reason to rather avoid templates: They actually force you to always take into account some less-than-truly-pure mechanism as copying. This means that your program may expose some anomalies w.r.t. monotonicity. You really have to look into the very details.
On the other hand without templates, as long as there is no copying involved, even your higher-order predicates will maintain monotonicity like a charm.
Considering your concrete example will make clear why a template is not needed for maplist/3:
In maplist/N and other higher-order predicates, you can use currying to fix a particular argument.
For example, you can write the predicate:
p(Z, X, Y) :-
Z #= X + Y.
And now your example works exactly as expected without the need for a template:
?- maplist(p(1), [1,2,3,4], [0,-1,-2,-3]).
true.
You can use library(lambda) to dynamically reorder arguments, to make this even more flexible.
What is the salient difference between these predicates?
findall/3 (and family, setof/3 and bagof/3) cannot be implemented in pure Prolog (the monotonic subset without side effects), while maplist/N is simply a kind of 'macro', implementing boilerplate list(s) visit.
In maplist/N nothing is assumed about the determinacy of the predicate, since the execution flow is controlled by the list(s) pattern(s). findall/3 it's a list constructor, and it's essential the goal terminate, and (I see) a necessity to indicate what to retain of every succeeded goal invocation.

Will using member within a forall clause in SWI-Prolog always output the elements in the same order?

Having recently got into Prolog I've been using it for a few simple tasks and began to wonder about using member within forall loops like the one in the trivial example below:
forall(member(A,[1,2,3,4]), print(A)).
In the case that you do something like this is it always true that forall will process the elements within the list in the same order every time its called? Does it have to be enforced by say doing something like:
A = [1,2,3,4], sort(A, B), forall(member(C,B), print(C)).
From what little research I've initially done I'm guessing that it comes down to the behaviour of member/2 but the documentation for the function on SWI-Prolog's website is very brief. It does however mention determinism with regards member/2 which gave me an inkling I might be on the right path in saying that it would always extract the elements in the same order, though I'm far from certain.
Can anyone give me any guarantees or explanations on this one?
Non-determinism in Prolog simply refers to a predicate having potentially more than one solution. Clearly, member/2 is such a predicate. This does not mean that you have to be worried about your computation becoming unpredictable. Prolog has a well-defined computation rule which essentially says that alternative solutions are explored in a depth-first, left-to-right manner. Thus your goal member(X,[1,2,3,4]) will generate solutions to X in the expected order 1,2,3,4.
Sorting the list [1,2,3,4] will not make any difference, as it is already sorted (according to Prolog's standard term order).
A word of caution about forall/2: some Prologs define this, but it is probably less useful than you imagine, because it is not really a "loop". You can use it in your example because you only perform a print side effect in each iteration. For most other purposes, you should familiarize yourself with recursive patterns like
print_list([]).
print_list([X|Xs]) :- print(X), print_list(Xs).
Strictly speaking, there is no guarantee in SWI on several levels:
1mo, that member/2 or forall/2 will perform in exactly this manner, since you can redefine them.
?- [user].
member(X,X).
|: % user://1 compiled 0.00 sec, 2 clauses
true.
?- forall(member(A,[1,2,3,4]), print(A)).
[1,2,3,4]
true.
However, member/2 is defined in the Prolog prologue which covers all the details you are interested in.
As for forall(A,B) it is safer to write \+ (A, \+B) instead, since this relies on standard features only. There is no definition of forall/2 as such, so it is difficult to tell what is the "right" behavior.
2do, that SWI will be standard conforming. If you read the documentation, you will note that there is no self-declaration (as for, e.g. SICStus Prolog) for standard conformance. In fact, \+ (A, \+B) is not fully conforming, as in the following example that should silently fail, but rather prints nonconforming
?- \+ ( C= !, \+ (C,fail;writeq(nonconforming))).
N208 has forall/2 defined + (call(Generator), + call(Test)), so this makes it less dubious. But by virtue that the ISO core standard (+)/1 does already a call/1 and that the ISO core standard (,)/2 will be subject to body conversion one can simply define it as follows in an ISO core standard Prolog:
forall(Generator, Test) :-
\+ (Generator, \+ Test).
SWI-Prolog has also implemented this way, and the error observed by Ulrich Neumerkel will not be seen when using forall/2:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.18)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
?- \+ ( C= !, \+ (C,fail;writeq(nonconforming))).
nonconforming
true.
?- forall(C=!, (C,fail;writeq(nonconforming))).
false.
Side remark:
I don't know how useful it is for loop. It seems to me using it for loops is not the right approach, since the test might fail, and then the construct also fails. I have also seen by Striegnitz and Blackburn the following definition of a helper predicate that they call failiure driven loop.
doall(Goal) :-
Goal, fail.
doall(_).
I find myself directly writing Goal, fail; true which also does the job:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.18)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
?- member(A,[1,2,3,4]), write(A), nl, fail; true.
1
2
3
4
true.

Prolog negation and logical negation

Assume we have the following program:
a(tom).
v(pat).
and the query (which returns false):
\+ a(X), v(X).
When tracing, I can see that X becomes instantiated to tom, the predicate a(tom) succeeds, therefore \+ a(tom) fails.
I have read in some tutorials that the not (\+) in Prolog is just a test and does not cause instantiation.
Could someone please clarify the above point for me? As I can see the instantiation.
I understand there are differences between not (negation as failure) and the logical negation. Could you refer a good article that explains in which cases they behave the same and when do they behave different?
Great question.
Short answer: you stumbled upon "floundering".
The problem is that the implementation of the operator \+ only works
when applied to a literal containing no variables, i.e., a ground
literal. It is not able to generate bindings for variables, but only
test whether subgoals succeed or fail. So to guarantee reasonable
answers to queries to programs containing negation, the negation
operator must be allowed to apply only to ground literals. If it is
applied to a nonground literal, the program is said to flounder.
link
If you invert the query
v(X), \+ a(X).
You'll get the right answer. Some implementations or meta interpreter detect floundering goals and delay them until all the variables are ground.
About your point 1), you see the instantiation inside the NAF tree. What happens there shouldn't affect variables that are outside (in this case in v(X)). Prolog often acts in the naive way to avoid inefficiencies. In theory it should just return an error instead of instantiating the variable.
2) This is my favourite article on the topic: Nonmonotonic Logic Programming.
WRT point 2, Wikipedia article seems a good starting point.
You already experienced that understanding NAF can be difficult. Part of this could be because (logical) negation it's inherently difficult to define even in simpler contest that predicate calculus (see for instance Russel's paradox), and part because the powerful variables of Prolog are domed to keep the actual counterexamples of failed if negated proofs. See if you can understand the actual library definition of forall/2 (please read the documentation, it's synthetic and interesting) that's the preferred way to run a failure driven loop:
%% forall(+Condition, +Action)
%
% True if Action if true for all variable bindings for which Condition
% if true.
forall(Cond, Action) :-
\+ (Cond, \+ Action).
I remember the first time I saw it, it looked like magic...
edit about a tutorial, I found, while 'spelunking' my links collection, a good site by J.R.Fisher. It's full of interesting stuff, just a pity it's a bit terse in explanations, requiring the student to answer itself with frequent execises. See the paragraph 2.5, devoted to negation by failure. I think you could also enjoy section 3. How Prolog Works

Resources