Node:Parameter Transfer, Previous:The Method Code, Up:Obj Expand



Parameter Transfer

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 ?