As can be seen in the expanded methods above, the second additional argument is simply ignored if the object has no parameter. In contrast regard the following objects:
ellipse(RX,RY,Color) :: { color(Color) & area(A) :- :(A is RX*RY*3.14159265) }. circle(R,Color) :: { super(ellipse(R,R,Color)) }. red_circle(R) :: { super(circle(R,red)) }.
... and their expansions:
ellipse(_, _, _):'$so_type'(ellipse(_,_,_), static). ellipse(_, _, _):area(A, _, B) :- B:'$fix_param'(ellipse(C,D,_), B), user:(A is C*D*3.14159265). ellipse(_, _, _):color(A, _, B) :- B:'$fix_param'(ellipse(_,_,A), B). ellipse(_, _, _):'$fix_param'(ellipse(B,C,D), A) :- objects:object_class(ellipse(B,C,D), A). circle(_, _):'$so_type'(circle(_,_), static). circle(_, _):super(ellipse(A,A,B), [], _, circle(A,B)). circle(_, _):'$fix_param'(circle(B,C), A) :- objects:object_class(circle(B,C), A). circle(_, _):'$fix_param'(ellipse(B,B,C), A) :- objects:object_class(circle(B,C), A). red_circle(_):'$so_type'(red_circle(_), static). red_circle(_):super(circle(A,red), [], _, red_circle(A)). red_circle(_):'$fix_param'(red_circle(B), A) :- objects:object_class(red_circle(B), A). red_circle(_):'$fix_param'(circle(B,red), A) :- objects:object_class(red_circle(B), A). red_circle(_):'$fix_param'(ellipse(B,B,red), A) :- objects:object_class(red_circle(B), A).
The second additional argument contains the receiver of a method
call. If the method makes use of any parameter of the object where it is
defined, it places a call to the reserved predicate $fix_param/2
in the module of the receiver. The purpose of this call is to bind the
parameters used in the method to appropriate values given by the
receiver. The receiver may be the object where the method is defined or
any of its subs. In order to service these calls, a clause of
$fix_param/2
is generated for each ancestor having
parameters. Such a clause may be regarded as the collapsed chain of
super/[1,2]
definitions leading up to the ancestor.
The call objects:object_class(
Class,
Object)
serves to
pick up the '$class'/1
attribute if Object is an instance;
otherwise, Class is unified with Object.
The following trace illustrates how parameters are transfered:
| ?- red_circle(2.5)::area(A). 1 1 Call: red_circle(2.5)::area(_A) ? 2 2 Call: ellipse(_,_,_):area(_A,red_circle(2.5),red_circle(2.5)) ? 3 3 Call: red_circle(_):$fix_param(ellipse(_B,_,_),red_circle(2.5)) ? 4 4 Call: objects:object_class(red_circle(_B),red_circle(2.5)) ? 4 4 Exit: objects:object_class(red_circle(2.5),red_circle(2.5)) ? 3 3 Exit: red_circle(_):$fix_param(ellipse(2.5,2.5,red),red_circle(2.5)) ? 5 3 Call: _A is 2.5*2.5*3.14159265 ? 5 3 Exit: 19.6349540625 is 2.5*2.5*3.14159265 ? 2 2 Exit: ellipse(_,_,_):area(19.6349540625,red_circle(2.5),red_circle(2.5)) ? 1 1 Exit: red_circle(2.5)::area(19.6349540625) ? A = 19.6349540625 ?