W terminologii XSB terminy Hilog są bardzo silnie powiązane z systemem modułów, który jest unikalny dla XSB. XSB ma system modułowy oparty na funktorach. Oznacza to, że w tym samym zakresie length(X)
może należeć do jednego modułu, podczas gdy length(L, N)
może należeć do innego. W konsekwencji call(length(L), N)
może odnosić się do jednego modułu do drugiego i call(length(L, N))
:
[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];
może się okazać, że w takim kontekście istnieją różnice między call/N
i Hilog warunkach. Jak dotąd jednak nie znalazłem.
Historycznie, terminy Hilog zostały wprowadzone w latach 1987-1989. W tym momencie, call/N
istniało już jako wbudowane w NU i jako library(call)
w Quintus Prolog z only cursory documentation. Zostało zaproponowane 1984 by Richard O'Keefe. Z drugiej strony, call/N
był wyraźnie nieznany autorom Hiloga, co ilustruje na przykład strona 111 Weidonga Chena, Michael Kifer, David Scott Warren: HiLog: A First-Order Semantyka dla wyższych klas programowania programowania logicznego. NACLP 1989. 1090-1114. MIT-Press.
... domknięcie przechodnie Generic może być również zdefiniowane w Prologu:
closure(R, X, Y) :- C =.. [R, X, Y], call(C).
closure(R, X, Y) :- C =.. [R, X, Z], call(C), closure(R, Z, Y).
Jednak jest to oczywiście nieeleganckie w stosunku do HiLog (patrz punkt 2.1), ponieważ wiąże się to zarówno budowy termin z listę i odzwierciedlenie tego terminu w formułę atomową za pomocą "połączenia". Istotą tego przykładu jest to, że brak teoretycznych podstaw dla konstruktów wyższego rzędu w Prologu skutkuje niejasną składnią, co częściowo tłumaczy, dlaczego programy Prolog obejmujące takie konstrukty są notorycznie trudne do zrozumienia.
Teraz można to zrobić z call/N
tak:
closure(R, X, Y) :- call(R, X, Y).
closure(R, X, Y) :- call(R, X, Z), closure(R, Z, Y).
Która jest bardziej ogólny niż (=..)/2
-version ponieważ R
nie jest już ograniczona do bycia atom. Na marginesie wolałbym napisać:
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).