All'interno di XSB, i termini Hilog sono fortemente collegati al sistema del modulo che è univoco per XSB. XSB ha un sistema di moduli basato su functor. Cioè, all'interno dello stesso ambito length(X)
potrebbe appartenere a un modulo, mentre length(L, N)
potrebbe appartenere a un altro. Di conseguenza, call(length(L), N)
potrebbero definire un modulo e call(length(L, N))
all'altro:
[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];
Potrebbe essere che in un tale contesto ci sono differenze tra call/N
e Hilog termini. Tuttavia, non l'ho ancora trovato.
Storicamente, i termini Hilog sono stati introdotti nel periodo 1987-1989. In quel momento, call/N
esisteva già come built-in in NU e come library(call)
in Quintus Prolog con only cursory documentation. È stato proposto 1984 by Richard O'Keefe. D'altra parte, call/N
era chiaramente sconosciuto agli autori di Hilog, come è esemplificato su p.1101 di Weidong Chen, Michael Kifer, David Scott Warren: HiLog: Un primo ordine Semantica per i costrutti di programmazione logica superiore. NACLP 1989. 1090-1114. MIT-Press.
... chiusura transitiva generico può anche essere definito 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).
Tuttavia, questo è ovviamente poco elegante rispetto al HiLog (vedi Sezione 2.1), dal momento che questo comporta sia la costruzione di un termine di una lista e che riflette questo termine in una formula atomica usando "call". Il punto di questo esempio è che la mancanza di basi teoriche per i costrutti di ordine superiore in Prolog ha prodotto un'oscura sintassi, che spiega in parte perché i programmi Prolog che coinvolgono tali costrutti sono notoriamente difficili da comprendere.
Ora, questo può essere fatto con call/N
in questo modo:
closure(R, X, Y) :- call(R, X, Y).
closure(R, X, Y) :- call(R, X, Z), closure(R, Z, Y).
che è ancora più generale di (=..)/2
-version perché R
non è più limitato ad essere un atomo. Per inciso, preferirei piuttosto scrivere:
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).