turning off Redefined static procedure in prolog - prolog

anyone of you could tell me how to turn off "Redefined static procedure" warnings?
I red online documentation of swi-prolog and i found this predicate no_style_check(ultimate) that in principle should turn off these warnings, but when i execute this predicate
main:-
no_style_check(singleton),
no_style_check(discontiguous),
no_style_check(multiple),
require,
test_all.
i received this error
ERROR: Domain error: style_name' expected, foundmultiple'
Anyone knows an alternative way to do this or could tell me why i receive this error ?
Thanks in advance!

Prolog is a pretty loosey-goosey language, so by default it warns you when you do certain things that are not wrong per se, but tend to be a good indication that you've made a typo.
Now, suppose you write something like this:
myfoo(3, 3).
myfoo(N, M) :- M is N*4+1.
Then from the prompt you write this:
?- asserta(myfoo(7,9)).
ERROR: asserta/1: No permission to modify static procedure `myfoo/2'
ERROR: Defined at user://1:9
What's happening here is that you haven't told Prolog that it's OK for you to modify myfoo/2 so it is stopping you. The trick is to add a declaration:
:- dynamic myfoo/2.
myfoo(3, 3).
myfoo(N, M) :- M is N*4+1.
Now it will let you modify it just fine:
?- asserta(myfoo(7,9)).
true.
Now suppose you have three modules and they each advertise themselves by defining some predicate. For instance, you might have three files.
foo.pl
can_haz(foo).
bar.pl
can_haz(bar).
When you load them both you're going to get a warning:
?- [foo].
true.
?- [bar].
Warning: /home/fox/HOME/Projects/bar.pl:1:
Redefined static procedure can_haz/1
Previously defined at /home/fox/HOME/Projects/foo.pl:1
true.
And notice this:
?- can_haz(X).
X = bar.
The foo solution is gone.
The trick here is to tell Prolog that clauses of this predicate may be defined in different files. The trick is multifile:
foo.pl
:- multifile can_haz/1.
can_haz(foo).
bar.pl
:- multifile can_haz/1.
can_haz(bar).
In use:
?- [foo].
true.
?- [bar].
true.
?- can_haz(X).
X = foo ;
X = bar.
:- discontiguous does the same thing as multifile except in a single file; so you define clauses of the same predicate in different places in one file.
Again, singleton warnings are a completely different beast and I would absolutely not modify the warnings on them, they're too useful in debugging.

Related

Representing truth regarding beliefs in prolog

How to make this (or something similar) work in Prolog:
belief(john,red(apple)).
belief(peter,red(apple)).
X :- belief(john,X), belief(peter,X).
And get true. for the following query (while consulting above):-
?- red(apple).
First, it's useful to define a little helper to capture when all (relevant) persons believe something:
all_believe(Belief) :-
belief(john, Belief),
belief(peter, Belief).
Then you can define, for example:
red(Object) :-
all_believe(red(Object)).
green(Object) :-
all_believe(green(Object)).
And with your given set of beliefs you get:
?- red(apple).
true.
?- green(apple).
false.
This works. It requires you to define similar rules for any term that you want to use as a belief.
You can make this a bit shorter with macro definitions using term_expansion:
term_expansion(declare_belief(Belief),
Belief :- all_believe(Belief)).
This means that every top-level definition in your source code of the form declare_belief(Belief) should be treated as if you had written Belief :- all_believe(Belief) instead (with the variable Belief substituted appropriately).
So now you can just write this:
declare_belief(red(_)).
declare_belief(green(_)).
and it will be treated exactly like the longer definitions for red(Object) and red(Object) above. You will still have to write this kind of declaration for any term that you want to use as a possible belief.
Prolog does not allow the head of a rule to be just a variable. The head must be a nonvar term, whose functor (i.e., name and arity) identifies the predicate being defined. So, a possible solution would be something like this:
true_belief(X) :-
belief(john, X),
belief(peter, X).
belief(john, red(apple)).
belief(peter, red(apple)).
Examples:
?- true_belief(red(apple)).
true.
?- true_belief(X).
X = red(apple).

How can I check that a particular constant exists in Prolog?

Say I have the following:
person(james).
person(pete).
father(james, pete).
Is there a way to validate that both the arguments to father have been defined i.e to stop a typo such as father(jmes, pete).
There is an easy way of checking these kinds of errors using Prolog: You can call rules at initialization time, i.e. one that checks that your fathers relations is properly defined. This can be useful to catch those typo errors.
:- use_module(library(error)).
check_fathers :-
% Take an element of the father relation
(father(P, _); father(_, P)),
% Proceed, if P is not a person
\+ person(P),
% Throw an error
syntax_error(father_is_no_person(P)).
check_fathers.
:- check_fathers.
person(james).
person(pete).
father(jame, pete). % TYPO! jame instead of james
Then, the program will produce the following output:
ERROR: Syntax error: father_is_no_person(jame)
Warning: <filename>:<line>:
Warning: Goal (directive) failed: user:check_fathers
Your assumptions are wrong in this sense:
father(james, pete). is a fact. It is something that you tell the Prolog processor is uneniably true (similar to a row in a table in a relational database).
So is father(jmes, pete).. Another fact. You are stating that this is so.
There is nothing to check, really.
On the other hand, if father(jmes, pete) appears in a a goal position, the Prolog processor will say "no, I have no indiciation that this is true":
father(james, pete). % that's a fat fact!
?- father(jmes, pete). % that's a query
false. % and the answer is "no, there is no evidence of that"
What you you would like to have is to have something like Java enum types: have the compiler make sure that a keyword comes indeed from a selected set of allowed keywords.
Prolog has has only basic typing, so this cannot be done directly.
But you could do this:
% if X is an unbound variable or a member of the indicated list,
% we are good
allowed_father(X) :-
(var(X);memberchk(X,[james,vader])),!.
% otherwise, we don't just fail, we actually throw an exception
allowed_father(X) :-
throw(error(unknown_father(X))).
% ---
% if X is an unbound variable or a member of the indicated list,
% we are good
allowed_son(X) :-
(var(X);memberchk(X,[pete,luke])),!.
% otherwise, we don't just fail, we actually throw an exception
allowed_father(X) :-
throw(error(unknown_son(X))).
and then you can call the above predicates whenever you need to perform a check:
query_anout(Father) :-
allowed_father(Father),
...
But it's rather awkward. Plus the thrown exception is not ISO-standard and the resulting error message may be confusing (I always rage against ISO standard exceptions which are doubleplusungood awkward)

On ways to work around an unexpected "Undefined procedure" error

NB: Just to be clear, my motivation for the question below is to learn my way around Prolog and SWI-Prolog, not to get past a particular error message. In fact, I already know one way to get past this error. My question asks about whether several other alternatives are also possible.
An exercise in my Prolog textbook asks one to describe the outcome one should expect from several queries, assuming one has consulted the following knowledgebase beforehand:
x(a).
z(b).
z(c).
z(d).
w(V) :- x(V).
w(V) :- y(V).
w(V) :- z(V).
On SWI-Prolog, at least, most of these queries fail, because SWI-Prolog intreprets y as undefined.
From the solutions to the exercises at the end of the book I can tell that this is not the authors' intended outcome. Maybe there's a Prolog implementation for which the exercise would turn as the solution presents it.
Be that as it may, I'd like to learn about good ways to work around the problem.
Consider, for example, the query w(x).. the book's solution claims that the query w(x). should evaluate to false.. In fact, this is what happens:
?- w(x).
ERROR: w/1: Undefined procedure: y/1
Exception: (7) y(x) ?
(At this point, SWI-Prolog is expecting me to enter some letter indicating how to respond to the exception. More about this later.)
I'm looking for ways to either turn the interaction above to
?- w(x).
false.
?-
...or at least for a suitable <ONE-LETTER RESPONSE> I could give to SWI-Prolog so that it arrives at the conclusion false. IOW, so that
?- w(x).
ERROR: w/1: Undefined procedure: y/1
Exception: (7) y(x) ? <ONE-LETTER RESPONSE>
false.
?-
I know of at least one answer to my question, namely simply to delete or comment out the line:
w(V) :- y(V).
I would like to know of other possible solutions, such as, for example, the "suitable " I alluded to earlier.
Another possibility would be some SWI-Prolog global configuration that would result in the above interaction to change to
?- w(x).
false.
?-
A third possibility would be to "define" y in some minimal way. The only way I can come up with is by adding the fact
y(dummy).
to the knowledgebase. Is there a more minimal way to define y, one that does not require introducing an extraneous constant into the domain of discourse?
(This is not specific to SWI)
The first Prolog systems back in the 1970s actually behaved in the way you describe. Soon it became apparent that this is a frequent source of errors. Simple misspellings remained undetected for too long. Current implementations produce a clean existence error. This is standard behaviour since 1995.
However, you can go back into the olden tymes with the ISO Prolog flag unknown which has three values error (default), fail, and warning.
?- inex.
ERROR: Undefined procedure: inex/0 (DWIM could not correct goal)
?- set_prolog_flag(unknown, fail).
Warning: Using a non-error value for unknown in the global module
Warning: causes most of the development environment to stop working.
Warning: Please use :- dynamic or limit usage of unknown to a module.
Warning: See http://www.swi-prolog.org/howto/database.html
true.
?- inex.
false.
?- set_prolog_flag(unknown, warning).
Warning: Using a non-error value for unknown in the global module
Warning: causes most of the development environment to stop working.
Warning: Please use :- dynamic or limit usage of unknown to a module.
Warning: See http://www.swi-prolog.org/howto/database.html
true.
?- inex.
Warning: toplevel: Undefined procedure: inex/0 (DWIM could not correct goal)
false.
As you can read above, SWI proposes to use a dynamic declaration in stead - which in turn has its own problems... It is much better to declare instead:
:- discontiguous(y/1).
An undefined procedure error raises an exception so if you want the exception to be raised because you don't want to change y/1 predicate (delete or define it) you need to catch the exception and then return false like this:
x(a).
z(b).
z(c).
z(d).
w(V) :- x(V).
w(V) :- catch(y(V), error(Err,_Context),my_handler(Err)).
w(V) :- z(V).
my_handler(Err):- write(Err),fail.
Example:
?- w(x).
existence_error(procedure,y/1)
false.

Prolog: subsets facts not working

I've never written in Prolog before. I have to provide facts so that when it runs it displays:
?- subset([a,b],[a,c,d,b]).
true.
?-include([],[a,b]).
true.
So far, I've written this:
subset([],_Y).
subset([X|T],Y):- member(X,Y),subset(T,Y).
But include doesn't work when I write include([],[a,b]). . It shows this:
ERROR: toplevel: Undefined procedure: include/2 (DWIM could not correct goal)
Any help would be appreciated. Thanks
You get the error because you didn't define the predicate include/2. Your given example looks like include/2 should be describing the same relation as subset/2. So you can either rename your definition from subset/2 to include/2 and then run the query or you can use subset/2 to define include/2:
include(X,Y) :-
subset(X,Y).
Note that in order to use member/2 you have to use library(lists). However, in some Prolog systems (e.g. SWI) this library includes a predicate subset/2 thus leading to a warning when you consult your source file:
Warning: ...
Local definition of user:subset/2 overrides weak import from lists
If you want to implement your own version of subset/2 anyway and not get this warning, you can rename your predicate or not use library(lists) and implement your version of member/2, for example:
subset([],_Y).
subset([X|T],Y) :-
element_in(X,Y),
subset(T,Y).
element_in(X,[X|_]).
element_in(X,[Y|Ys]) :-
dif(X,Y),
element_in(X,Ys).

singleton variables in prolog

I was testing my new version of SWI prolog and keep coming across the error :singleton variable.
Example:
member(X,[X|T]).
member(X,[X|T]) :- member(X,T).
finds the member of a list such as :
member(yolands,[yolanda,tim])
X = yes
but instead I get a singleton variables error for X and T
if I do the following:
member(X,[X|_]).
member(X,[_|T]) :- member(X,T).
It works but looks ugly!
Can anyone explain why single variables ar enot allowed and if this ANSI standard?
Singleton variables are useless in Prolog, and are easily introduced by editing typos.
The warning is welcome to me, as it allows to easily spot such frequent cause of error.
Being a warning, you can run code containing singletons, but any value these eventually will assume will be lost.
I don't think that ISO standard (never heard about ANSI) forbids such variables.
You could rewrite your example in this way
member(X, [Y|T]) :- X = Y ; member(X, T).
and then forget about the singleton.
You have a bug here:
member(X,[X|T]) :- member(X,T).
What you're actually saying (as opposed to what you think you're saying) is that member/2 holds if X is at the head of the list and present in the tail of the list. This predicate will only ever be true for the first N copies of the same thing at the beginning of a list, so it's a very strange thing to say!
?- member(X, [a,a,c]).
X = a ;
X = a ;
false.
?- member(X, [b,a,a]).
X = b ;
false.
Now, you could correct the bug and still have a singleton warning by doing something like this:
member(X, [Y|T]) :- member(X, T).
But this is neither as good as the conventional definition with two heads or #CapelliC's version (+1) with an explicit OR. I think you should wait until you understand Prolog a little better before putting much stock in your sense of Prolog code aesthetics. If you stick with it for a while you'll come to appreciate this warning as well as the use of anonymous variables.
What makes singleton variables useless in Prolog is that they're named but nothing is known about them and they have no effect on the rest of the computation. The underscore highlights that absolutely anything could go in there without affecting the meaning. What makes
member(X, [X|T]).
true is that the X is position 1 is the same as the X at the head of the list in position 2. Lists must either be empty or have a head and a tail, but what's in the tail is not relevant here, what matters is that X is also the head. The T could be the rest of the list, or it could be an improper list, or it could be a breadbox or lightning or the smell of the air on a spring day. It has no bearing on the truth of member(X, [X|T]).
The singleton warning tells you "you've reserved a name for something here, but you never call anything by that name." The first thing I do when I get this message and it isn't an obvious typo is replace the name with _ and see if my code still makes sense. If it doesn't, I have a logic error. If it does, it was probably unnecessary.
You can read about it on the official page of SWI-Prolog FAQ
The most common cases this warning appears are:
Spelling mistakes in variables
Forget to use/bind a variable
SWI suggest some ways to ignore it:
Use anonymous variable named _ for this purpose.
Use your variable starting with _ (like _T, _X), to avoid warning and document what you ignore.
If you are aware of what you are doing, you can use :- style_check(-singleton). and all warnings should go away.

Resources