In XSB, Hilog terms are very strongly associated with a modular system that is unique to XSB. XSB has a functor-based modular system. That is, within one region, length(X) can belong to one module, while length(L, N) can belong to another. As a result, call(length(L), N) can 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];
Perhaps in this context there are differences between the terms call/N and Hilog. However, I have not yet found it.
Historically, Khilog terms were introduced in 1987-1989. At this point, call/N already existed as a built-in NU and library(call) in Quintus Prolog with only a fluent document . 1984 was proposed by Richard O'Keefe . On the other hand, call/N was clearly unknown to the authors of Khilog, as shown on page 1101 Weidong Chen, Michael Kifer, David Scott Warren: HiLog: First Order Semantics for constructing higher-order logical programming. NACLP 1989.1090-1114. MIT-Press.
... In the Prolog, the general transitive closure can also be defined:
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 clearly inelegant compared to HiLog (see Section 2.1), since this includes both constructing a term from a list and reflecting this term in an atomic formula using a βcallβ. The essence of this example is that the lack of theoretical foundations for higher-order constructs in Prolog led to an unclear syntax, which partially explains why Prolog programs with such constructs are known to be difficult to understand.
Now this can be done using call/N as follows:
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 no longer limited to an atom. As an aside, I would rather 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).