Search code examples
prologlogtalk

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


How to use the 'Univ' ( =../2 ) prolog predicate with a Logtalk object method as parameter ?

Consider this code :

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.

I'll obtain :

?- {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

What workaround to use for a good interpretation / compilation ? It seems issue is the same with swi-prolog building predicate like predsort/3 (predsort/3 doc).


Solution

  • The standard =../2 predicate expects, when constructing a term from a list, that the first list argument be an atom but bar::baz is a compound term with functor ::/2 (which is both defined as a predicate - for top-level queries - and as an operator when Logtalk is loaded). The solution is to write instead:

    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.
    

    With this changes, you get:

    ?- {univ}.
    % [ /Users/pmoura/Desktop/univ.lgt loaded ]
    % (0 warnings)
    true.
    
    ?- run.
    baz(foo(testfoo))
    predicatetestfoo
    
    bar::baz(foo(testfoo))
    predicatetestfoo
    
    true.