[Xotcl] "Simple Delegation" revisited (long post)

Sheik Yussuff sheik@carib-link.net
Sun, 8 Jul 2001 14:10:09 -0300


This is a multi-part message in MIME format.

------=_NextPart_000_000B_01C107B7.B25AF6C0
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

Just over 6 months ago,Catherine Letondal raised

the issue of implementing "simple delegation".

Professor G. Neumann replied with some code showing

how it can be done as well as suggesting that one may

use a filter to filter all methods or an instmixin

to target specific methods for delegation.

I am now learning Tcl and XOTcl (a week or so now)at the

same time and have decided to try the filter approach.

The Experiment:

1. Create a meta-class SimpleDelegation

2. add a filter sdFilter to this meta-class

3. add an instproc setDelegate

4. Create classes A and B using SimpleDelegate

5. Create class C using Class

6. A has as delegate(instvar) an object of class B;

B has as delegate an object of class C

7. A,B and C has a method "m" defined

The Problem: (Using Windows binary ver 0.85)

I extended Prof. Neumann's code to handle above

and it works.(see Code1 below)

My experiment(Code 2) works only for the following

cases(that I tested):

1. A,B and C has a method "m".

2. The instvar delegate removed from B

It does not work when I rename the method

"m" in class C to "m2".

In this case I expect an object of class B to

execute "m" but instead I get an object of class

A executing "m" instead.

I would be grateful for any pointers to resolve

this problem.

Also I want to try to implement delegation as

described by Prof. Lieberman(OOPSLA 1986 paper).

Will be grateful for any pointers on this also.

...............

Code1: Prof Neumann's code inelegantly extended

Class A -parameter delegate

A instproc handleDelegation {result} {

if {[[self] exists delegate]} {

set context [::info level -1]

#look for method in delegated object

if {[[[self] set delegate] procsearch [lindex $context 0]] !=3D "" } {

::upvar $result y

set y [eval [[self] set delegate] $context]

return 1

}

}

return 0

}

A instproc m {x} {

if {[[self] handleDelegation r]} {

return $r

} else {

puts "[self] [self class] [self proc] $x";

return [next]

}

}

Class B -parameter delegate

B instproc handleDelegation {result} {

if {[[self] exists delegate]} {

set context [::info level -1]

#look for method in delegated object

if {[[[self] set delegate] procsearch [lindex $context 0]] !=3D "" } {

::upvar $result y

set y [eval [[self] set delegate] $context]

return 1

}

}

return 0

}

B instproc m {x} {

if {[[self] handleDelegation r]} {

return $r

} else {

puts "[self] [self class] [self proc] $x";

return [next]

}

}

Class D

D instproc m2 {x} {

puts "[self] [self class] [self proc] $x"

next

return [expr {$x*2 + [[self] set v]}]

}

D d1

d1 set v 100

B b1 -delegate d1

A a1 -delegate b1

puts "result =3D [a1 m 123]"

...............................................

Code2: My Try using filters

#create SimpleDelegation as a meta-class

Class SimpleDelegation -superclass Class

SimpleDelegation instproc sdFilter args {

set method [self calledproc]

if {[[self] exists delegate]} {

set del [[self] set delegate]

#if delegate has method then dispatch it.

if {[$del procsearch $method] !=3D ""} {

return [eval [$del $method $args]]

}=20

return [next];

}

}

SimpleDelegation instproc init args {

[self] filterappend [self class]::sdFilter

next

[self] instproc setDelegate {d} {

[self] set delegate $d

}

}

SimpleDelegation A -parameter delegate

SimpleDelegation B -parameter delegate



A instproc m {x} {

puts "[self] [self class] [self proc] $x"

return [next]

}

B instproc m {x} {

puts "[self] [self class] [self proc] $x"

next

return [expr {$x*2 + [[self] set v]}]

}

Class C

#method "m" renamed to "m2" here.

C instproc m2 {x} {

puts "[self] [self class] [self proc] $x"

next

return [expr {$x*3 + [[self] set v]}]

}

A a

B b

a setDelegate b

b set v 100

C c

b setDelegate c

c set v 100

puts "result =3D [a m 123]"

..................................................

Regards,

Sheik Yussuff

email: sheik@carib-link.net


------=_NextPart_000_000B_01C107B7.B25AF6C0
Content-Type: text/html;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content=3D"text/html; charset=3Diso-8859-1" =
http-equiv=3DContent-Type>
<META content=3D"MSHTML 5.00.2614.3500" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT size=3D2>
<P>Just over 6 months ago,Catherine Letondal raised</P>
<P>the issue of implementing "simple delegation".</P>
<P>Professor G. Neumann replied with some code showing</P>
<P>how it can be done as well as suggesting that one may</P>
<P>use a filter to filter all methods or an instmixin</P>
<P>to target specific methods for delegation.</P>
<P>I am now learning Tcl and XOTcl (a week or so now)at the</P>
<P>same time and have decided to try the filter approach.</P>
<P>The Experiment:</P>
<P>1. Create a meta-class SimpleDelegation</P>
<P>2. add a filter sdFilter to this meta-class</P>
<P>3. add an instproc setDelegate</P>
<P>4. Create classes A and B using SimpleDelegate</P>
<P>5. Create class C using Class</P>
<P>6. A has as delegate(instvar) an object of class B;</P>
<P>B has as delegate an object of class C</P>
<P>7. A,B and C has a method "m" defined</P>
<P>The Problem: (Using Windows binary ver 0.85)</P>
<P>I extended Prof. Neumann's code to handle above</P>
<P>and it works.(see Code1 below)</P>
<P>My experiment(Code 2) works only for the following</P>
<P>cases(that I tested):</P>
<P>1. A,B and C has a method "m".</P>
<P>2. The instvar delegate removed from B</P>
<P>It does not work when I rename the method</P>
<P>"m" in class C to "m2".</P>
<P>In this case I expect an object of class B to</P>
<P>execute "m" but instead I get an object of class</P>
<P>A executing "m" instead.</P>
<P>I would be grateful for any pointers to resolve</P>
<P>this problem.</P>
<P>Also I want to try to implement delegation as</P>
<P>described by Prof. Lieberman(OOPSLA 1986 paper).</P>
<P>Will be grateful for any pointers on this also.</P>
<P>...............</P>
<P>Code1: Prof Neumann's code inelegantly extended</P>
<P>Class A -parameter delegate</P>
<P>A instproc handleDelegation {result} {</P>
<P>if {[[self] exists delegate]} {</P>
<P>set context [::info level -1]</P>
<P>#look for method in delegated object</P>
<P>if {[[[self] set delegate] procsearch [lindex $context 0]] !=3D "" } =
{</P>
<P>::upvar $result y</P>
<P>set y [eval [[self] set delegate] $context]</P>
<P>return 1</P>
<P>}</P>
<P>}</P>
<P>return 0</P>
<P>}</P>
<P>A instproc m {x} {</P>
<P>if {[[self] handleDelegation r]} {</P>
<P>return $r</P>
<P>} else {</P>
<P>puts "[self] [self class] [self proc] $x";</P>
<P>return [next]</P>
<P>}</P>
<P>}</P>
<P>Class B -parameter delegate</P>
<P>B instproc handleDelegation {result} {</P>
<P>if {[[self] exists delegate]} {</P>
<P>set context [::info level -1]</P>
<P>#look for method in delegated object</P>
<P>if {[[[self] set delegate] procsearch [lindex $context 0]] !=3D "" } =
{</P>
<P>::upvar $result y</P>
<P>set y [eval [[self] set delegate] $context]</P>
<P>return 1</P>
<P>}</P>
<P>}</P>
<P>return 0</P>
<P>}</P>
<P>B instproc m {x} {</P>
<P>if {[[self] handleDelegation r]} {</P>
<P>return $r</P>
<P>} else {</P>
<P>puts "[self] [self class] [self proc] $x";</P>
<P>return [next]</P>
<P>}</P>
<P>}</P>
<P>Class D</P>
<P>D instproc m2 {x} {</P>
<P>puts "[self] [self class] [self proc] $x"</P>
<P>next</P>
<P>return [expr {$x*2 + [[self] set v]}]</P>
<P>}</P>
<P>D d1</P>
<P>d1 set v 100</P>
<P>B b1 -delegate d1</P>
<P>A a1 -delegate b1</P>
<P>puts "result =3D [a1 m 123]"</P>
<P>...............................................</P>
<P>Code2: My Try using filters</P>
<P>#create SimpleDelegation as a meta-class</P>
<P>Class SimpleDelegation -superclass Class</P>
<P>SimpleDelegation instproc sdFilter args {</P>
<P>set method [self calledproc]</P>
<P>if {[[self] exists delegate]} {</P>
<P>set del [[self] set delegate]</P>
<P>#if delegate has method then dispatch it.</P>
<P>if {[$del procsearch $method] !=3D ""} {</P>
<P>return [eval [$del $method $args]]</P>
<P>} </P>
<P>return [next];</P>
<P>}</P>
<P>}</P>
<P>SimpleDelegation instproc init args {</P>
<P>[self] filterappend [self class]::sdFilter</P>
<P>next</P>
<P>[self] instproc setDelegate {d} {</P>
<P>[self] set delegate $d</P>
<P>}</P>
<P>}</P>
<P>SimpleDelegation A -parameter delegate</P>
<P>SimpleDelegation B -parameter delegate</P>
<P>&nbsp;</P>
<P>A instproc m {x} {</P>
<P>puts "[self] [self class] [self proc] $x"</P>
<P>return [next]</P>
<P>}</P>
<P>B instproc m {x} {</P>
<P>puts "[self] [self class] [self proc] $x"</P>
<P>next</P>
<P>return [expr {$x*2 + [[self] set v]}]</P>
<P>}</P>
<P>Class C</P>
<P>#method "m" renamed to "m2" here.</P>
<P>C instproc m2 {x} {</P>
<P>puts "[self] [self class] [self proc] $x"</P>
<P>next</P>
<P>return [expr {$x*3 + [[self] set v]}]</P>
<P>}</P>
<P>A a</P>
<P>B b</P>
<P>a setDelegate b</P>
<P>b set v 100</P>
<P>C c</P>
<P>b setDelegate c</P>
<P>c set v 100</P>
<P>puts "result =3D [a m 123]"</P>
<P>..................................................</P>
<P>Regards,</P>
<P>Sheik Yussuff</P>
<P>email: sheik@carib-link.net</P></FONT></DIV></BODY></HTML>

------=_NextPart_000_000B_01C107B7.B25AF6C0--