Hilog terms in (XSB) Prolog

2019-02-21 17:36发布

问题:

Are Hilog terms (i.e. compounds having as functors arbitrary terms) still regarded as a powerful feature in XSB Prolog (or any other Prolog) ? Are there many XSB projects currently using this feature ? which of them for example ?

I ask since as far as I understand higher order programming is equally possible using the ISO built-in call/N.

Specifically, I would like to understand if XSB is using Hilog terms just for historical reasons or if Hilog terms have considerable advantages in comparison to the current ISO standard.

回答1:

Within XSB, Hilog terms are very strongly connected to the module system which is unique to XSB. XSB has a functor based module system. That is, within the same scope length(X) might belong to one module, whereas length(L, N) might belong to another. As a consequence, call(length(L), N) might refer to one module and call(length(L, N)) to another:

[Patch date: 2013/02/20 06:17:59]
| ?- use_module(basics,length/2).
yes
| ?- length(Xs,2).             
Xs = [_h201,_h203]
yes
| ?- call(length(Xs),2).
Xs = [_h217,_h219]
yes
| ?- use_module(inex,length/1). 
yes
| ?- length(Xs,2).
Xs = [_h201,_h203]
yes
| ?- call(length(Xs),2).
++Error[XSB/Runtime/P]: [Existence (No module inex exists)]  in arg 1 of predicate load
| ?- call(call(length,Xs),2).
Xs = [_h228,_h230];

It might be that in such a context there are differences between call/N and Hilog terms. I have, however, so far not found one.

Historically, Hilog terms have been introduced 1987-1989. At that point in time, call/N already existed as built-ins in NU and as library(call) in Quintus Prolog with only cursory documentation. It has been proposed 1984 by Richard O'Keefe. On the other hand, call/N was clearly unknown to the authors of Hilog, as is exemplified on p.1101 of Weidong Chen, Michael Kifer, David Scott Warren: HiLog: A First-Order Semantics for Higher-Order Logic Programming Constructs. NACLP 1989. 1090-1114. MIT-Press.

... Generic transitive closure can also be defined in Prolog:

    closure(R, X, Y) :- C =.. [R, X, Y], call(C).
    closure(R, X, Y) :- C =.. [R, X, Z], call(C), closure(R, Z, Y). 

However, this is obviously inelegant compared to HiLog (see Section 2.1), since this involves both constructing a term out of a list and reflecting this term into an atomic formula using "call". The point of this example is that the lack of theoretical foundations for higher-order constructs in Prolog resulted in an obscure syntax, which partially explains why Prolog programs involving such constructs are notoriously hard to understand.

Now, this can be done with call/N like so:

closure(R, X, Y) :- call(R, X, Y).
closure(R, X, Y) :- call(R, X, Z), closure(R, Z, Y).

Which is even more general than the (=..)/2-version because R is no longer restricted to being an atom. As an aside, I'd rather prefer to write:

closure(R_2, X0,X) :- call(R_2, X0,X1), closure0(R_2, X1,X).

closure0(_R_2, X,X).
closure0(R_2, X0,X) :- call(R_2, X0,X1), closure0(R_2, X1,X).