extend user object

Help requests on developing Logtalk applications

Moderator: Paulo Moura

Post Reply
shengcer
Posts: 21
Joined: Wed Aug 14, 2013 7:54 pm

extend user object

Post by shengcer » Fri Aug 16, 2013 6:32 pm

Hi, sorry, it is me again.

Using swi-Prolog as the underlying compiler, I made my object extend the "user" object, and then tried to call "concat_atom" inside the object, which failed with

Code: Select all

*     This predicate is called but never defined: concat_atom/3
*       in file /home/shengcer/test/orange.lgt between lines 15-17
*       while compiling object orange
My object def is like this,

Code: Select all

:- object(orange, extends([user])) .
  concat(X, Y, Z) :-
    concat_atom([X, Y], ',', Z) .
:- end_object .
I tried to call user::concat_atom directly in the console, and it worked

Code: Select all

 3 ?- user::concat_atom(['a', 'b'], ',', V) .
V = 'a,b'.
I also noticed inside orange object body, I can call predicates such as findall and call, but not append, exclude or maplist. Also if I replace "concat_atom" with "user::concat_atom" within the object def, i.e.,

Code: Select all

:- object(orange, extends([user])) .
  concat(X, Y, Z) :-
    user::concat_atom([X, Y], ',', Z) .
:- end_object .
it is also working.

why does this happen? How should I properly call the integrated predicate supplied by the underlying prolog engine?

shengcer
Posts: 21
Joined: Wed Aug 14, 2013 7:54 pm

Re: extend user object

Post by shengcer » Fri Aug 16, 2013 8:01 pm

New problems,

I am trying to call the built-in predicates directly by referring to "user" predicate,

Code: Select all

public(isfruit/3)
...
user::maplist(fruit::isfruit(X), Hs0, Hs) ,
user::concat_atom(Hs, ',', Value) .
It failed with error

Code: Select all

ERROR: apply:maplist_/3: Undefined procedure: (::)/4
ERROR:   However, there are definitions for:
ERROR:         (::)/2
if I change fruit::isfruit -> isfruit, it ended with this error

Code: Select all

ERROR: apply:maplist_/3: Undefined procedure: isfruit/3
exclude has the similar problem, if a predicate with partially applied argument is referred as an argument.
These code all used to be able to run in SWI-prolog.
Last edited by shengcer on Fri Aug 16, 2013 8:04 pm, edited 1 time in total.

Paulo Moura
Logtalk developer
Posts: 475
Joined: Sat May 05, 2007 8:35 am
Location: Portugal
Contact:

Re: extend user object

Post by Paulo Moura » Fri Aug 16, 2013 8:03 pm

"user" is a pseudo-object that basically represents everything that's not encapsulated. Not meant to be used as a parent prototype, i.e to be extend.

The concat_atom/3 is a deprecated SWI-Prolog, available from the "backward_compatibility" library. But you're not making that information available to the Logtalk compiler (hence the warning) using e.g. a use_module/2 directive inside the object. Prefixing its call by "user::" allows it to be compiled as-is (i.e. the Logtalk compiler is bypassed) and the SWI-Prolog auto-loading mechanism to kick in. For append/3, which is also not a built-in predicate, you can use either the SWI-Prolog "lists" library or the Logtalk "list" object. In the first case, you need to add to your object the directive:

Code: Select all

:- use_module(lists, [append/3]).
In the second case, you need to load the "list" library object:

Code: Select all

?- {library(types_loader)}.
and then you can either use:

Code: Select all

..., list::append(...), ...
or:

Code: Select all

:- uses(list, [append/3]).

..., append(...), ...
For meta-predicates such as exclude/3 and maplist/2 you can use the Logtalk library as well:

Code: Select all

?- {library(metapredicates_loader}.

..., meta::map(...), ...
See the compatibility notes on SWI-Prolog ("adapters/NOTES.txt") and the library documentation ("library/docs/index.html") for more information. Also recommended reading is the User Manual section on Prolog integration and migration.
Paulo Moura
Logtalk developer

Paulo Moura
Logtalk developer
Posts: 475
Joined: Sat May 05, 2007 8:35 am
Location: Portugal
Contact:

Re: extend user object

Post by Paulo Moura » Fri Aug 16, 2013 8:11 pm

shengcer wrote:New problems,

I am trying to call the built-in predicates directly by referring to "user" predicate,

Code: Select all

public(isfruit/3)
...
user::maplist(fruit::isfruit(X), Hs0, Hs) ,
user::concat_atom(Hs, ',', Value) .
It failed with error

Code: Select all

ERROR: apply:maplist_/3: Undefined procedure: (::)/4
ERROR:   However, there are definitions for:
ERROR:         (::)/2
By prefixing the predicate call by "user::", you're bypassing the Logtalk compiler.
shengcer wrote: if I change fruit::isfruit -> isfruit, it ended with this error

Code: Select all

ERROR: apply:maplist_/3: Undefined procedure: isfruit/3
exclude has the similar problem, if a predicate with partially applied argument is referred as an argument.
These code all used to be able to run in SWI-prolog.
Neither maplist/3 or concat_atom/3 are built-in predicates. Note that you can check the properties of a SWI-Prolog predicate using the built-in predicate predicate_property/2. For example:

Code: Select all

?- predicate_property(concat_atom(_,_,_), Property).
Property = interpreted ;
Property = visible ;
Property = imported_from(backward_compatibility) ;
Property = file('/Users/pmoura/lib/swipl-6.5.1/library/backcomp.pl') ;
Property = line_count(213) ;
Property = number_of_clauses(1) ;
Property = number_of_rules(1) ;
false.
See my previous post on how to properly call predicates such as maplist/3 from within an object.
Paulo Moura
Logtalk developer

shengcer
Posts: 21
Joined: Wed Aug 14, 2013 7:54 pm

Re: extend user object

Post by shengcer » Sat Aug 17, 2013 11:27 pm

Thanks a lot! As you suggested, I noticed call, and findall are built-in predicates for logtalk, which is why they can be used in the object body directly. For the others, I have opted to use the logtalk's meta library, and it worked like a charm. One quick question for loading the standard library though -- I can run {library(metapredicates_loader)} in the console, but how can I import them in a loader file? I have tried to put that {library(metapredicates_loader)} inside and outside the :-initialization {...} , but neither works. Also what is the trick that the curly brace does? If I run "library(metapredicates_loader) ." in the console, I got non-existent predicate error.

Please point me to the part of the documentation that I can look for the answers to if you think it might be better this way. I know I have kept throwing questions these days in the forum, and I really appreciate your always quick response and patient explanation :-) I also would like to thank you for inventing this beautiful and powerful language, which I believe all java developers who have an interest developing jpl based application should seriously consider switching their prolog code to.


Paulo Moura wrote:
shengcer wrote:New problems,

I am trying to call the built-in predicates directly by referring to "user" predicate,

Code: Select all

public(isfruit/3)
...
user::maplist(fruit::isfruit(X), Hs0, Hs) ,
user::concat_atom(Hs, ',', Value) .
It failed with error

Code: Select all

ERROR: apply:maplist_/3: Undefined procedure: (::)/4
ERROR:   However, there are definitions for:
ERROR:         (::)/2
By prefixing the predicate call by "user::", you're bypassing the Logtalk compiler.
shengcer wrote: if I change fruit::isfruit -> isfruit, it ended with this error

Code: Select all

ERROR: apply:maplist_/3: Undefined procedure: isfruit/3
exclude has the similar problem, if a predicate with partially applied argument is referred as an argument.
These code all used to be able to run in SWI-prolog.
Neither maplist/3 or concat_atom/3 are built-in predicates. Note that you can check the properties of a SWI-Prolog predicate using the built-in predicate predicate_property/2. For example:

Code: Select all

?- predicate_property(concat_atom(_,_,_), Property).
Property = interpreted ;
Property = visible ;
Property = imported_from(backward_compatibility) ;
Property = file('/Users/pmoura/lib/swipl-6.5.1/library/backcomp.pl') ;
Property = line_count(213) ;
Property = number_of_clauses(1) ;
Property = number_of_rules(1) ;
false.
See my previous post on how to properly call predicates such as maplist/3 from within an object.

Paulo Moura
Logtalk developer
Posts: 475
Joined: Sat May 05, 2007 8:35 am
Location: Portugal
Contact:

Re: extend user object

Post by Paulo Moura » Sun Aug 18, 2013 1:41 am

shengcer wrote: Thanks a lot! As you suggested, I noticed call, and findall are built-in predicates for logtalk, which is why they can be used in the object body directly. For the others, I have opted to use the logtalk's meta library, and it worked like a charm.
That's a good idea for two reasons. First, it helps in making your code portable (to all Logtalk supported backend Prolog compilers). Second, the library includes a compiler that eliminates the overhead of using those meta-predicates. See the "metapredicates" and "metapredicates_compiled" examples in the Logtalk distribution.
shengcer wrote: One quick question for loading the standard library though -- I can run {library(metapredicates_loader)} in the console, but how can I import them in a loader file? I have tried to put that {library(metapredicates_loader)} inside and outside the :-initialization {...} , but neither works. Also what is the trick that the curly brace does? If I run "library(metapredicates_loader) ." in the console, I got non-existent predicate error.
The {...} notation is just a shorthand (defined in the adapter files) for logtalk_load/1, which is handy during interactive development. In a loader file simply write:

Code: Select all

:- initialization((
    ...,
    logtalk_load(library(metapredicates_loader)),
    ...
)).
shengcer wrote: Please point me to the part of the documentation that I can look for the answers to if you think it might be better this way. I know I have kept throwing questions these days in the forum, and I really appreciate your always quick response and patient explanation :-) I also would like to thank you for inventing this beautiful and powerful language, which I believe all java developers who have an interest developing jpl based application should seriously consider switching their prolog code to.
Happy that you're having fun programming in Logtalk :-) Besides the User Manual, I suggest that you take some time to look into the examples. There are many of them but the "examples/NOTES.txt" file gives a brief description of each one. That should help you select the ones that may be more relevant for your application.
Paulo Moura
Logtalk developer

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest