使用 "univ" Prolog 谓词和 Logtalk 对象方法作为参数

Use "univ" Prolog predicate with a Logtalk object method as parameter

如何使用带有 Logtalk 对象方法作为参数的“Univ”(=../2)prolog 谓词?

考虑这段代码:

baz(foo(X)) :-
  write(predicate), write(X), nl.

run :-
    Term =.. [baz, foo(testfoo)],
    write(Term), nl, Term,nl,    
    TermLgt =.. [bar::baz, foo(testfoo2)],
    write(TermLgt), nl, Term,nl.    

:- object(bar).

  :- public(baz/1).
  baz(foo(X)) :-
    write(method), write(X), nl.

:- end_object.

:- object(main).

  :- public(run/0).
  run :-
    Term =.. [baz, foo(testfoo)],
    write(Term), nl, Term,nl,    
    TermLgt =.. [bar::baz, foo(testfoo2)],
    write(TermLgt), nl, Term,nl.

:- end_object.

我会得到:

?- {myfile}.
% (0 warnings)
true.

?- run.
baz(foo(testfoo))
predicatetestfoo

ERROR: =../2: Type error: `atom' expected, found `bar::baz' (a compound)

?- main::run.
baz(foo(testfoo))
ERROR: Undefined procedure: baz/1
ERROR:   However, there are definitions for:
ERROR:         baz/1

使用什么变通方法来进行良好的解释/编译?似乎问题与 swi-prolog 构建谓词相同 predsort/3 (predsort/3 doc).

标准的 =../2 谓词期望,当从一个列表构造一个术语时,第一个列表参数是一个原子,但是 bar::baz 是一个带有函子 ::/2 的复合术语(它既定义为谓词 - 对于顶级查询 - 又定义为加载 Logtalk 时的运算符)。解决方案是改写:

baz(foo(X)) :-
    write(predicate), write(X), nl.


run :-
    Term =.. [baz, foo(testfoo)],
    write(Term), nl, call(Term), nl,    
    TermLgt =.. [::, bar, Term],
    write(TermLgt), nl, call(Term), nl.    


:- object(bar).

    :- public(baz/1).
    baz(foo(X)) :-
        write(method), write(X), nl.

:- end_object.


:- object(main).

    :- public(run/0).
    run :-
        Term =.. [baz, foo(testfoo)],
        write(Term), nl, Term,nl,    
        TermLgt =.. [::, bar, Term],
        write(TermLgt), nl, Term,nl.

:- end_object.

通过此更改,您将获得:

?- {univ}.
% [ /Users/pmoura/Desktop/univ.lgt loaded ]
% (0 warnings)
true.

?- run.
baz(foo(testfoo))
predicatetestfoo

bar::baz(foo(testfoo))
predicatetestfoo

true.