Recommendations for implementing predicates such as dif / 2

Suppose I have a predicate foo/2that defines the relationship between its first and second argument.

What is the most idiomatic and effective way to change an implementation foo/2so that:

  • if both its arguments are grounded, it acts as before (succeeds if the relation is fulfilled, it does not work otherwise).

  • if one of the two arguments (or both) is free, it “holds back” these two arguments, so that when they are grounded, the relation will be checked.

In other words, how to properly implement the behavior shown dif/2, but with any kind of user relationship?

listing(dif/2). did not help.

+4
source share
2 answers

Different Prolog implementations provide different possibilities for this. The mechanism is known differently as companion, delayed goals, restrictions, and your Prolog guide will provide more information.

Here are two options that are available in SICStus Prolog , as well as some other systems.

block/1 directive

In SICStus Prolog (and, possibly, in some other systems), one way to raise a user predicate for such a limited version is available through declarative . block

Interestingly, this does not require any changes to the predicate itself!

Suppose you have an unclean version dif/2using a nonmonotonic predicate (\=)/2:

madif (X, Y): -
    X \ = Y.

, :

:- block madif(-, ?),
         madif(?, -).

madif(X, Y) :-
    X \= Y.

:

| ?- madif(a, b).
yes
| ?- madif(a, X).
user:madif(a,X) ? ;
no
| ?- madif(a, X), X = b.
X = b ? ;
no
| ?- madif(X, Y).
user:madif(X,Y) ? ;
no

, .

when/2

SICStus Prolog ( , ) - when/2. .

, when/2, madif/2 :

madif(X, Y) :-
    when((ground(X),
          ground(Y)), X \= Y).

:

| ?- madif(X, a).
prolog:trig_ground(X,[],[X],_A,_A),
prolog:when(_A,(ground(X),ground(a)),user:(X\=a)) ? ;
no
| ?- madif(X, a), X = b.
X = b ? ;
no
+2

,

..., . – . . , , .

, . , , , , . , freeze(_, G_0). , , . SICStus 1 SWI call_residue_vars(Query_0, Vs), .

, . , , . , difgrn/2 dif/2:

difgrn(X, Y) :-
   when((ground(X), ground(Y)), X \== Y).

| ?- difgrn(X, X).
prolog:trig_ground(X,[],[X],_A,_B),
prolog:trig_ground(X,[],[X],_A,_C),
prolog:trig_and(_C,[],_A,_B,_A),
prolog:when(_A,(ground(X),ground(X)),user:(X\==X)) ? ;
no
| ?- dif(X, X).
no


| ?- difgrn([], [_]).
prolog:trig_ground(_A,[],[_A],_B,_C),
prolog:trig_and(_C,[],_B,1,_B),
prolog:when(_B,(ground([]),ground([_A])),user:([]\==[_A]))

| ?- dif([], [_]).
yes

dif/2 (?=)/2:

difwh(X,Y) :- when(?=(X,Y), X\==Y).

:

, , dif/2, ?

, , .

, . X in 1..2, dif(X, 1), dif(X, 2).

(- .) - - , , . . trig_ground , , , .

, , , frozen/2 copy_term/3.

. subsumes_term/2, . . freeze(X, Y = a) , Y. Y ( freeze/2), , Y b.

, dif/2 (1972, Prolog 0). L'anatomie de Prolog, Interditions 1986 Lee Naish MU-Prolog.


1 . library(clpfd) assert(clpfd:full_answer).

+2

Source: https://habr.com/ru/post/1670183/


All Articles