Is this a bug? (!;_+_)

I’m using: SWI-Prolog version 8.4.1 ,


% this fails:
(ins)?- (!;_+_).
ERROR: Unknown procedure: (+)/2 (DWIM could not correct goal)

% this succeeds:
(ins)?- A=(!;_+_), A.
A =  (!;_+_).

Regards.

Have you used write_canonical/1 to understand the differences?


(ins)?- write_canonical( A=(!,_+_)).
=(_,','(!,+(_,_)))
true.

(cmd)?- A=(!,_+_), write_canonical( A).
','(!,+(_,_))
A =  (!, _+_).

(ins)?- write_canonical( (!, _+_)).
','(!,+(_,_))
true.

I think so.

What I mean is to use write_canonical/1 to look at the term in a different perspective. You used it correctly but now look at the results and see if it changes how you think about the term.

This is the sound of the one hand clapping.

To be honest I see no difference.

I can just assume that the plain term gets compiled and maybe optimized and the stored term gets only interpreted. It did not even change anything if I used expand_term / expand_goal.

Btw. it would be interesting to be able to compile several prolog predicates or terms into compiled ones. I remember in R is this possibe. Nice feature.

Sorry I am doing this and something else.

Look at the primary functor of each.

One is = and the other is ;.

When I see = I think data and when I see ; I think predicates. Does that lead you in the right direction?

Did you oversee that I call A after initializing it?

(ins)?- A=(!;_+_), A.
A =  (!;_+_).

(ins)?- A=(!;_+_), call(A).
A =  (!;_+_).

Indeed I made a mistake on using write_canonical.

?- A=(!;_+_), write_canonical( A).
;(!,+(_,_))
A =  (!;_+_).

?- write_canonical( (!;_+_)).
;(!,+(_,_))
true.

?- write_canonical( A=(!;_+_)).
=(_,;(!,+(_,_)))
true.

% as expected

But I think we should have a little overview:


?- A=(false,_+_), A.
false.

?- (false,_+_).
ERROR: Unknown procedure: (+)/2 (DWIM could not correct goal)

?- (false,_).
false.

?- A=(!;_+_), A.
A =  (!;_+_).

?- (!;_+_).
ERROR: Unknown procedure: (+)/2 (DWIM could not correct goal)

?- (!;_).
true.


1 Like

I have it:

?- _.
% ... 1,000,000 ............ 10,000,000 years later
% 
%       >> 42 << (last release gives the question)
(ins)?- 

(ins)?- A=_, call(A).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR:   [10] '<meta-call>'(user:user: ...)
ERROR:    [9] toplevel_call(user:user: ...) at /usr/local/lib/swipl/boot/toplevel.pl:1117

% a little bit inconsistent

The inconsistency doesn’t seem to come from call/1, but rather from the interactive toplevel. Your example ! ; _+_. should normally succeed, no matter how you execute it. For example, all of the following work:

% Define it as a predicate, then call that predicate:
?- [user].
|: foo :- ! ; _+_.
|: ^D% user://1 compiled 0.01 sec, 1 clauses
true.

?- foo.
true.

% Place it in a directive:
?- [user].
|: :- ! ; _+_.
|: ^D% user://2 compiled 0.00 sec, 0 clauses
true.

% Load it from a file:
?- [some_file].
true.

?- foo_from_file.
true.

?- listing(foo_from_file).
foo_from_file :-
    (   !
    ;   _+_
    ).

true.

The only case that fails is when you directly type it in interactively:

?- ! ; _+_.
ERROR: Unknown procedure: (+)/2 (DWIM could not correct goal)

I think this is caused by the DWIM (do what I mean) system, which is mentioned in the error. DWIM searches all interactive inputs for incorrect predicate names, so that it can offer possible corrections for e. g. typos or missing module prefixes. (Try executing pront(hello). for example.) A side effect seems to be that if DWIM sees an incorrect predicate call anywhere in your input, and it can’t find any possible corrections, then it throws an error and doesn’t try to execute your input at all.

In most cases this is helpful, because it tells you the error more quickly than Prolog normally would. For example, with the following input, DWIM reports the mistyped name right away, whereas in normal execution it would run the long calculation before noticing the undefined predicate.

?- some_long_calculation(Res), writterm(_, []).
ERROR: Unknown procedure: writterm/2 (DWIM could not correct goal)

But in cases where for some reason you really want to have incorrect predicate calls in your input, DWIM’s behavior can be a bit confusing and counterproductive.

3 Likes

This makes sense. Thank you for the explanation.

If you want to test how the system responds to wrong input, yes. There is a work-around: wrap (part of) the query inside call/1. Because it makes little sense to use call/1 in toplevel queries the DWIM system doesn’t look inside (it does look inside other meta predicates). A case where this is useful is where loading a file makes the predicate available, e.g.,

?- [load], call(go).

Here, ?- [load], go. would cause DWIM to complain go/0 does not exist.

2 Likes