call with "::" in predicate used with a meta-predicate

Help requests on developing Logtalk applications

Moderator: Paulo Moura

Post Reply
Victor NOEL
Posts: 48
Joined: Tue May 15, 2007 4:53 pm

call with "::" in predicate used with a meta-predicate

Post by Victor NOEL » Wed May 28, 2008 4:11 pm

Hello,

I am playing with the meta predicate meta::map.

I have this code in a class

Code: Select all

:- private(expand/3).
my_expand(T, B, NewT) :-
  T = neg(NT) -> (::expand(NT, B, NNewT), NewT = neg(NNewT)) ; (::expand(T, B, NewT)).
unexpand(Binding, A, B) :- my_expand(B, Binding, A).

dojob(Binding, Support, UnextandedSupport) :- meta::map(unexpand(Binding), Support, UnextandedSupport)
expand/3 is implemented in an object instantiating this class.

and when I call dojob/3 on the object instantiating the class, I get this error :

Code: Select all

ERROR: Unhandled exception: Unknown message: error(existence_error(predicate_declaration, expand(_G8, t(me, seller1, t(it, buyer1, t, t), t(product, bottle, t, t(proposition, high_price, t, t))), _G10)), meta::expand(_G8, t(me, seller1, t(it, buyer1, t, t), t(product, bottle, t, t(proposition, high_price, t, t))), _G10), tharg)
(tharg is the class and Binding is a bintree (dictionaryp))

How can I transform my code to do what I want ?

Thanks for your help.

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

Re: call with "::" in predicate used with a meta-predicate

Post by Paulo Moura » Thu May 29, 2008 11:04 am

Victor NOEL wrote: ...
and when I call dojob/3 on the object instantiating the class, I get this error :

Code: Select all

ERROR: Unhandled exception: Unknown message: error(existence_error(predicate_declaration, expand(_G8, t(me, seller1, t(it, buyer1, t, t), t(product, bottle, t, t(proposition, high_price, t, t))), _G10)), meta::expand(_G8, t(me, seller1, t(it, buyer1, t, t), t(product, bottle, t, t(proposition, high_price, t, t))), _G10), tharg)
(tharg is the class and Binding is a bintree (dictionaryp))

How can I transform my code to do what I want ?

Thanks for your help.
I've copied your code above to a class, declared the predicate my_expand/3 as public, and added a fact for the predicate expand/3 to a class instance. I'm unable to reproduce the error above. Try to find the most simple example that allows you to reproduce the problem.

Best regards,

Paulo
Paulo Moura
Logtalk developer

Victor NOEL
Posts: 48
Joined: Tue May 15, 2007 4:53 pm

Re: call with "::" in predicate used with a meta-predicate

Post by Victor NOEL » Thu May 29, 2008 11:57 am

Ok, this is a simple example :

Code: Select all

:- object(theobject, instantiates(theclass)).

  expand(a, 1).
  expand(b, 2).
  expand(c, 3).

:- end_object.

:- object(theclass, specializes(logtalk)).

  :- private([expand/2]).
  :- public([dojob/2]).

  dojob(From, To) :-
	meta::map(unexpand, From, To).

  unexpand(Expanded, Unexpanded) :- ::expand(Unexpanded, Expanded).

:- end_object.
And when I run it :

Code: Select all

?- theobject::dojob([1, 2, 3], D).
ERROR: Unhandled exception: Unknown message: error(existence_error(predicate_declaration, expand(_G8, 1)), meta::expand(_G8, 1), theclass)

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

Re: call with "::" in predicate used with a meta-predicate

Post by Paulo Moura » Thu May 29, 2008 2:36 pm

Hi!

Meta-predicates call meta-arguments in the context of the sender. In your example, the sender is the object "theclass". The predicate unexpand/2 is defined in "theclass", so your map/3 message to "meta" is correct. However, the predicate unexpand/2 calls the predicate expand/2 in the context of self. The trouble is that, in this case, self is the object "theclass", not the object "theobject". When the meta-predicate calls the unexpand/2 predicate it longer have access to the value of self associated in the original dojob/2 message. You may find this behavior too restrictive. It is, however, the behavior necessary to avoid the misuse of meta-predicates to break object encapsulation.

Best regards,

Paulo
Paulo Moura
Logtalk developer

Victor NOEL
Posts: 48
Joined: Tue May 15, 2007 4:53 pm

Re: call with "::" in predicate used with a meta-predicate

Post by Victor NOEL » Thu May 29, 2008 2:43 pm

Paulo Moura wrote: You may find this behavior too restrictive. It is, however, the behavior necessary to avoid the misuse of meta-predicates to break object encapsulation.
Ok, I understand : )

Do you have a recommended way to do what I want ?
For now, I wrote a predicate that do the job of map, and I can keep it like that : )

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

Re: call with "::" in predicate used with a meta-predicate

Post by Paulo Moura » Thu May 29, 2008 3:28 pm

Victor NOEL wrote: Do you have a recommended way to do what I want ?
You can use the following ugly workaround:

Code: Select all

:- object(theclass, specializes(logtalk)).

	:- public(expand/2).
	:- public(dojob/2).

	dojob(From, To) :-
		self(Self),
		meta::map(unexpand(Self), From, To).

	unexpand(Self, Expanded, Unexpanded) :-
		Self::expand(Unexpanded, Expanded).

:- end_object.


:- object(theobject, instantiates(theclass)).

	expand(a, 1).
	expand(b, 2).
	expand(c, 3).

:- end_object.
Victor NOEL wrote: For now, I wrote a predicate that do the job of map, and I can keep it like that : )
You can always copy the definition of the map/3 predicate from the library. Of course, as far as performance is concerned, speaking of Prolog in general, the best is to avoid the use of meta-predicates in the first place.

Best regards,

Paulo
Paulo Moura
Logtalk developer

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest