mthom / scryer-prolog

A modern Prolog implementation written mostly in Rust.
BSD 3-Clause "New" or "Revised" License
2.08k stars 125 forks source link

Is cut a predicate? #707

Closed ghost closed 2 years ago

ghost commented 4 years ago

The following happens:

?- !.
caught: error(existence_error(procedure,!/0),!/0)
?- 

While:

?- true, !.
   true.
?- !, true.
   true.
?- 
mthom commented 4 years ago

No. Rather, "!" is interpreted by the (,)/2 predicate, which is being called in your examples.

ghost commented 4 years ago

So some inputs to (',')/2 change the execution of the engine.

But ! also changes the execution of (;)/2:

?- ! ; true.
   true.
?- true ; !.
   true
;  true.
?- 

And:

?- [user].
a :- !.
a :- write(a), nl.

?- a.
   true.
?- 

It's not a predicate, what would it be?

pmoura commented 4 years ago

It's not a predicate, what would it be?

In the ISO Prolog Core standard, the cut is a control construct, not a (built-in) predicate.

ghost commented 4 years ago

Thank you, I understand now, it's like true/0, closing.

UWN commented 4 years ago

@notoria: Why close this? It is still a problem that there is an existence error. After all, the procedure (see 3.136 in case of doubt) !/0 is defined as static and private. Idem call(!). There is no responsibility of (',')/2 to interpret its arguments. Instead, there is 7.6.2 Converting a term to the body of a clause.

(That is: Of course (',')/2 and other control constructs may take the burden of 7.6.2 by itself. But at least conceptually, there is just one such term-to-body conversion prior to calling such constructs - see e.g. 7.8.3.1 f.)

UWN commented 4 years ago
?- call((G_0=!, G_0)).
   G_0 = !.
?- call((G_0=!, call(G_0))).
caught: error(existence_error(procedure,!/0),!/0)        % unexpected
?- call((G_0=!, G_0 ; Snd = true )).
   G_0 = !.                                              % missing alternative Snd = true
?- call((G_0=!, call(G_0) ; Snd = true )).
caught: error(existence_error(procedure,!/0),!/0))       % unexpected

Maybe this better illustrates what is currently happening. Upon call/1, the argument should undergo a term-to-body conversion, effectively replacing (G_0=!, G_0 ; Snd = true ) by (G_0=!, call(G_0) ; Snd = true). But it seems that conversion is never performed (it does not need to be performed some as-if alternate interpretation would be good enough).

mthom commented 2 years ago

This is now fixed in rebis-dev.