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.
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).