For Programmers: Free Programming Magazines  


Home > Archive > Tcl > May 2004 > XOTcl and mixins









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author XOTcl and mixins
Helmut Giese

2004-05-18, 5:31 am

Hello out there,
mixins are a powerful feature but they are a bit cumbersome to use if
they posess variables of their own. The script below shows that if you
want to have such a mixin, you have to completely create / configure
it at the time the "holder" of the mixin is created.
Works, but I wonder if there is another way. The tutorial says
---
When a mixin is registered after object creation and it needs
initializations, it is necessary to define special methods for this.
---
Any ideas, what these 'special methods' might look like?
Best regards
Helmut Giese
---
#
# Mixins with own variables
#

package require XOTcl
namespace import -force xotcl::*

Class Base -parameter {{id 007}}
Base instproc show {} {
puts "Base show of [self]: id = [my set id]"
}

# Mixin class
Class Mix -parameter {{mixId 99}}

Mix instproc init {} {puts "Mix [self] is being created"}

Mix instproc show {} {
puts "Mix show of [self]: id = [my set id], mixId = [my set
mixId]"
next
}

Base b
b show
puts ""

# add the mixin
b mixin Mix
# error: "can't read "mixId": no such variable"
#b show

# this works
Base b2 -mixin Mix -mixId 33 -init -id 008
b2 show
puts ""

# try to use default values for mixin:
# "can't read "mixId": no such variable"
Base b3 -mixin Mix -init -id 008
b3 show
---
Gustaf Neumann

2004-05-18, 3:43 pm

hgiese@ratiosoft.com (Helmut Giese) wrote in message news:<40a9c923.3712744@News.Individual.DE>...
> Hello out there,
> mixins are a powerful feature but they are a bit cumbersome to use if
> they posess variables of their own.


Hi Helmut,

The default values of parameters are set during initialization
of an object (before "init" is called, such that the constructor
can depend on it) . This makes the usage more complicated, if you
want to specify default values for objects which are already created.

Note that there mixins and instmixins. The mixins are
for instantiated objects, the instmixins are specified for
classes and therefore available when the object is created.
So you can use in your script
Base instmixin Mix
somewhere before creating instances, if that is possible.

Another approach is to overload the mixin method as shown
below; maybe we can make this more pretty in future version.
I have simplified your script in a few places...

best regards
-gustaf
========================================
=======================

package require XOTcl
namespace import -force xotcl::*

Object instproc init {} { puts "[self] is created" }

Class Base -parameter {{id 007}}
Base instproc show {} {
puts "Base show of [self]: id = [my id]"
}

# Mixin class
Class Mix -parameter {{mixId 99}}
Mix instproc show {} {
next
puts "Mix show of [self]: id = [my id], mixId = [my mixId]"
}

Base b
b show
puts ""

# overload mixin method such it searches for default
# values of parameters after mixins are registered
Base instproc mixin args {
next
[[my info class] info parameterclass] searchDefaults [self]
}

# add the mixin
b mixin Mix
b show
puts ""

# specify all values
Base b2 -mixin Mix -mixId 33 -id 008
b2 show
puts ""

# try to use default values for mixin:
Base b3 -mixin Mix -id 009
b3 show
Helmut Giese

2004-05-18, 6:32 pm

On 18 May 2004 11:52:31 -0700, neumann@wu-wien.ac.at (Gustaf Neumann)
wrote:

Hello Gustaf,
thanks for the example.
>
>Note that there mixins and instmixins. The mixins are
>for instantiated objects, the instmixins are specified for
>classes and therefore available when the object is created.
>So you can use in your script
> Base instmixin Mix
>somewhere before creating instances, if that is possible.

As I understood, all instances of Base would then have Mix inserted -
which is not what I want.

>Another approach is to overload the mixin method as shown
>below; maybe we can make this more pretty in future version.

I would never have dreamed this up- even seeing it I barely understand
it, but then it works.

>I have simplified your script in a few places...

I noticed you left out the '-init' in
Base b2 -mixin Mix -mixId 33 -init -id 008
I took this syntax from the (very good, btw) tutorial on page 35.

This is my first shot at XOTcl - being an old C++ guy I feel quite
comfortable with Incr Tcl. However, it was just this 'mixin' feature
which looked very interesting for my current project.
What I would find promising is to have more control over the mixin
(please note that the mixins I am thinking of have variables of their
own). So what I can do now is
a) define all my mixin's variables when mixing it in at the moment the
'holder' object is created,
b) or do the mixin (at any moment in time) using the mixin's default
values.

For the sake of discussion let's just forget about default values and
assume the existence of variables (in the mixin) which are initially
undefined, forcing us to define them "somehow".
Then I don't see a possibility to replace a mixin with another one:
- the 'holder' object's moment of creation is long gone so
- all I can 'mix-in' is the class - no way to define my mixin's
variables.
(Could be I am completely wrong here - would be nice if it were the
case.)

What this amounts to is probably another method which complements
mixin and instmixin (objmixin, for want of a better word):
- instmixin (a class): affects all instances of the 'holder' class
- mixin (a class): affects just this particular 'holder' object
- objmixin (an already created object of the mixin class): affects
just the particular 'holder' object where the mixin occurred, but
since the mixed-in object is created explicitly, you woud have full
control over it.

However, for the moment method (a) from above is completely sufficient
for my needs - sort of creating a mixin once and never changing it.

Thanks for a powerful addition to Tcl and best regards
Helmut Giese
Andreas Leitgeb

2004-05-19, 6:31 am

Helmut Giese <hgiese@ratiosoft.com> wrote:
> b) or do the mixin (at any moment in time) using the mixin's default
> values.


This is a general problem, not limited to mixins:
Class Foo -parameter {{a 42} {b 32}}
Class Bar -parameter {{a 84} {c 64}}
Foo x
x a ;# --> 42
x b ;# --> 32
x class Bar
x a ;# --> 42 (not re-init'ed)
x b ;# --> unable to dispatch method 'b' (of course)
x c ;# --> Can't find result of parameter c (not init'ed)

And this isn't yet all of it: what if Foo's superclass is
changed lateron to something else that infers yet another
set of parameters.

Class Snafu -parameter {{a 52} {d 99}}
Bar superclass Snafu
x info methods ;# --> a b a c d a ...
x d ;# --> Can't find result of parameter d

Which instances of Bar should then be (re-)initialized? (all or none?)

PS: Btw, even though b isn't accessible while x is of class Bar,
it's previous value is restored, when x is changed back to Foo or
Foo is mixin'd to x. It's reasonable and odd at the same time :-)

Helmut Giese

2004-05-19, 6:31 am

On 19 May 2004 09:00:50 GMT, Andreas Leitgeb
<avl@gamma.logic.tuwien.ac.at> wrote:

Hi Andreas,
you're way ahead of me :)

Coming from a C++ background I have no mental model of a class
hierarchy or a situation where I would want to switch classes around.
The way I have been brought up :) if x is of class Car I wouldn't
dream of considering that I could change x to be of class Toaster or
introduce a new superclass, say Book, for Car.

I am just exploring (some of) the possibilities offered by the mixin
feature within my mental model of class hierachies. But it is of
course interesting to explore other models and see what possibilities
they offer.
Thanks for your examples
Helmut Giese

Gustaf Neumann

2004-05-19, 11:32 am

hgiese@ratiosoft.com (Helmut Giese) wrote in message news:<40aa6aa9.4912986@News.Individual.DE>...
> On 18 May 2004 11:52:31 -0700, neumann@wu-wien.ac.at (Gustaf Neumann)
> wrote:
>
> Hello Gustaf,
> thanks for the example.
> ...
> I would never have dreamed this up- even seeing it I barely understand
> it, but then it works.


it is certainly not a beginner example.

> I noticed you left out the '-init' in
> Base b2 -mixin Mix -mixId 33 -init -id 008
> I took this syntax from the (very good, btw) tutorial on page 35.


via "-init" one can control the time when init should be called.
if "-init" is not specified it is called after configure, otherwise
during configure..... Most people should not have to care about this.

> For the sake of discussion let's just forget about default values and
> assume the existence of variables (in the mixin) which are initially
> undefined, forcing us to define them "somehow".
> Then I don't see a possibility to replace a mixin with another one:
> - the 'holder' object's moment of creation is long gone so
> - all I can 'mix-in' is the class - no way to define my mixin's
> variables.
> (Could be I am completely wrong here - would be nice if it were the
> case.)
>
> What this amounts to is probably another method which complements
> mixin and instmixin (objmixin, for want of a better word):
> - instmixin (a class): affects all instances of the 'holder' class
> - mixin (a class): affects just this particular 'holder' object
> - objmixin (an already created object of the mixin class): affects
> just the particular 'holder' object where the mixin occurred, but
> since the mixed-in object is created explicitly, you woud have full
> control over it.


in other words, you are interested in stateful mixins, which are
sometimes called roles in the literature; many variants of those exist.
in general it is not only necessary to "mix-in" state, you also might
be interested to "mix it out" at some later time. In some situations,
you might be interested in multiple role instances for a single object),
(for example if you have an object Person and you
have the role ProjectLeader, where the ProjectLeader might be Leader
of multiple projects).

There are certainly many ways to implement such requirements, with
and without XOTcl. XOTcl's mixins are a light-weight language
construct which can help to implement such a thing.

Maybe you can follow the following approach:
- define a Mixin for the behavior to be mixed in
- define a class for the role-specific state
- define a method to add the role to an object.
This method registers the mixin, creates an instance
of the role-specific-state class and adds
a subobject to the "holder" object, as you called it.
The subobject holds the role-instance specific state.
- you can also define a method for unregistering
and removing the subobject.

in genereal, this process can can be recursive, the role-object
might have sub-roles, etc, you might have role-varialbles
similar to class variables, etc.

hope, this helps......
all the best
-gustaf neumann

> However, for the moment method (a) from above is completely sufficient
> for my needs - sort of creating a mixin once and never changing it.
>
> Thanks for a powerful addition to Tcl and best regards
> Helmut Giese

Andreas Leitgeb

2004-05-19, 12:33 pm

Helmut Giese <hgiese@ratiosoft.com> wrote:
><avl@gamma.logic.tuwien.ac.at> wrote:
> Hi Andreas,
> you're way ahead of me :)

no, no, I just went a different way:
I tried this and that, and hope that once I run across a real
problem I'll remember which of all my playings might help me :-)

> if x is of class Car I wouldn't dream of considering that I could
> change x to be of class Toaster or introduce a new superclass, say
> Book, for Car.

:-)

So,

class Item {
public:
enum t_type { Car, Book, Toaster=Car };
t_type mytype;
Item(t_type t) {mytype=t;}
};
Item myThingie(Car);
myThingie.type=Toaster;

looks more familiar? :-)

> I am just exploring (some of) the possibilities offered by the mixin
> feature within my mental model of class hierachies. But it is of
> course interesting to explore other models and see what possibilities
> they offer.

The point I was trying to make is, that once an object is created,
no more default-values are placed into the instance, unless explicitly
done. Furthermore it *cannot* be done automatically, because then this
would also have to happen for all the less obvious cases...

Gustaf Neumann

2004-05-21, 12:35 pm

hgiese@ratiosoft.com (Helmut Giese) wrote in message news:<40ab2921.4193580@News.Individual.DE>...
> On 19 May 2004 09:00:50 GMT, Andreas Leitgeb
> <avl@gamma.logic.tuwien.ac.at> wrote:
>
> Hi Andreas,
> you're way ahead of me :)
>
> Coming from a C++ background I have no mental model of a class
> hierarchy or a situation where I would want to switch classes around.
> The way I have been brought up :) if x is of class Car I wouldn't
> dream of considering that I could change x to be of class Toaster or
> introduce a new superclass, say Book, for Car.


but things change somtimes their types. If you drive a
car into a Tree, it can be a wreck afterwards, if you have classes
like Student, Employee, Manager, people change the classes
(or get roles assigned) over time. This is more often a problem
with systems with persistent data.

One major difference between languages like C++ and XOTcl is
that all variables "live" in the objects and the relationship
between an object and a class is a relationship, not something
like a class-instance-record, that determines the storage size
of the object. The relation between classes are as well
mutable relations. Similarly, the relation between
an instance variable and an object is a relation
managed through a hash table.

xotcl does not prevent you to do foolish things, but it allows
you sometimes to do clever things with little effort.

-gustaf
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com