Hi,
I'm a long-time Perl programmer who recently started using XOTcl on a new project. Support for mixins has been a tremendous boon for productivity on this project.
However, the standard idioms for managing mixins (mixin and mixinappend) both feel a little broken. For example, with "obj mixin list_of_classes", I need to know the full set of mixins for an object (or a class) each time I mutate it. Using mixinappend helps, but appending new classes to the end of the mixin list seems wrong, because the newly added classes will be found *last*.
Here is why I think these idioms don't work well: in most other languages, an object is created through successive refinement. In C++/Java, we start with a base class and derive more and more specific variants on that definition through subclassing. I use XSLT a lot, and in XSLT, the most specific templates are found after templates of lesser specificity. Surely there are other examples; these are just the first two that come to my mind. The underlying idiom seems universal, at least to me.
To remedy this, I've added this primitive into my system. Suggestions for better names greatfully appreciated:
Object instproc insert_mixin {mixin_list} { my mixin [append mixin_list " " [my info mixin]] }
With this new operation, I can now derive an object through mixins in a very natural manner:
Car mycar mycar insert_mixin Volkswagen mycar insert_mixin NewBeetle mycar insert_mixin AutomaticTransmission mycar insert_mixin Turbo mycar insert_mixin WasabiGreen ....
If I were to start calling methods like "max_rpm", "engine_size", "color", or "transmission", they can all get intercepted at the right point in the mixin chain, wrapping/superceding more generic methods. Instant separation of concerns. ;-)
Additionally, I can dynamically refine my object:
if {$add_roof_rack} { mycar insert_mixin RoofRack }
if {$has_sunroof} { mycar insert_mixin SunRoof }
Thanks for the excellent programming environment. Hope this helps,
-- Adam
Hi Adam,
I agree that mixinappend is not always the best choice; I had this problem once in one of my projects as well. I remember that I once wanted to introduce {inst}[mixin|filter]prepend, but obviously haven't done it ... to introduce the following in the next XOTcl version should be no problem, I think:
::xotcl::Object instproc filterprepend f { ::xotcl::my filter [concat $f [::xotcl::my info filter -guards]] } ::xotcl::Object instproc mixinprepend m { ::xotcl::my mixin [concat $m [::xotcl::my info mixin]] } ::xotcl::Class instproc instfilterprepend f { ::xotcl::my instfilter [concat $f [::xotcl::my info instfilter -guards]] } ::xotcl::Class instproc instmixinprepend m { ::xotcl::my instmixin [concat $m [::xotcl::my info instmixin]] }
--uwe
Adam Turoff wrote:
Hi,
I'm a long-time Perl programmer who recently started using XOTcl on a new project. Support for mixins has been a tremendous boon for productivity on this project.
However, the standard idioms for managing mixins (mixin and mixinappend) both feel a little broken. For example, with "obj mixin list_of_classes", I need to know the full set of mixins for an object (or a class) each time I mutate it. Using mixinappend helps, but appending new classes to the end of the mixin list seems wrong, because the newly added classes will be found *last*.
Here is why I think these idioms don't work well: in most other languages, an object is created through successive refinement. In C++/Java, we start with a base class and derive more and more specific variants on that definition through subclassing. I use XSLT a lot, and in XSLT, the most specific templates are found after templates of lesser specificity. Surely there are other examples; these are just the first two that come to my mind. The underlying idiom seems universal, at least to me.
To remedy this, I've added this primitive into my system. Suggestions for better names greatfully appreciated:
Object instproc insert_mixin {mixin_list} { my mixin [append mixin_list " " [my info mixin]] }
With this new operation, I can now derive an object through mixins in a very natural manner:
Car mycar mycar insert_mixin Volkswagen mycar insert_mixin NewBeetle mycar insert_mixin AutomaticTransmission mycar insert_mixin Turbo mycar insert_mixin WasabiGreen ....
If I were to start calling methods like "max_rpm", "engine_size", "color", or "transmission", they can all get intercepted at the right point in the mixin chain, wrapping/superceding more generic methods. Instant separation of concerns. ;-)
Additionally, I can dynamically refine my object:
if {$add_roof_rack} { mycar insert_mixin RoofRack } if {$has_sunroof} { mycar insert_mixin SunRoof }
Thanks for the excellent programming environment. Hope this helps,
-- Adam
Xotcl mailing list - Xotcl@alice.wu-wien.ac.at http://alice.wu-wien.ac.at/mailman/listinfo/xotcl
Hi there,
Object instproc insert_mixin {mixin_list} { my mixin [append mixin_list " " [my info mixin]] }
with names like mixinappend, mixinprepend for mixins, filters, instmixins, instfilters we would introduce a large number of methods, which do more or less the same.
what do you people think about the following "interceptor" method: it is more verbous, but much more powerful as well; it allows appending/prepending/inserting at a certain position and deletion of all kinds of interceptors:
================================================ Object instproc interceptor {op kind name {pos 0}} { switch -exact $op { add {my $kind [linsert [my info $kind] $pos $name]} delete { set old [my info $kind] set p [lsearch -glob $old $name] if {$p>-1} {my $kind [lreplace $old $p $p]} else { error "$name not in $old" } } } puts "$kind list: [my info $kind]" }
Class A Class B Class C
Object o o interceptor add mixin A o interceptor add mixin B o interceptor add mixin C end o interceptor delete mixin *A ================================================ The output of this script is:
mixin list: ::A mixin list: ::B ::A mixin list: ::B ::A ::C mixin list: ::B ::C
best regards -gustaf neumann