Hi!
Learnable lazy wrapper per unknown mechanism. Should one do such magic thinks?
package require XOTcl namespace import ::xotcl::* package require struct::queue
Class Queue -parameter {{queue [self]::queue}}
Queue instproc init {} { ::struct::queue [my queue] } Queue instproc destroy {} { [self]::queue destroy next } Queue instproc unknown {args} { # some debbug puts "learning [lindex $args 0]" Queue instforward [lindex $args 0] {%my queue} %proc # maybe learn only if that calls success eval [self]::queue $args }
Testing
(bin) 31 % Queue create q1 ::q1 (bin) 32 % q1 put 32 learning put (bin) 33 % q1 put 43 (bin) 34 % q1 get learning get 32 (bin) 35 % q1 get 43 (bin) 35 %
Artur
mail@xdobry.de schrieb:
Learnable lazy wrapper per unknown mechanism. Should one do such magic thinks?
one can use "unknown" by itself for implementing the task, or to register a forwarder (i have used the same approach in http://wiki.tcl.tk/11033).
I am not a particular friend of unknown, except for error handling. i see three reasons against it.
1) "unknown" does not mix well with mixins. The program semantics can change, when mixins are added (see below) 2) only unknown commands are forwarded. What if you want to forward a method, that happens to be defined by some classes. Try to forward e.g. append by this approach (somewhat related to (1) 3) all unknown commands are forwarded (can easily be fixed)
generally i prefer to use the explicit "create" over the unknown handler to create objects (using "Object create o1" instead of "Object o1"), except that the shortcut is much nicer to read. If one defines user methods on classes, the unknown is dangerous as well, one might define a method o1, typos can easily turn up as created objects.
This as a side node "unknown considered harmful".
So, the apporach via "unknown" is interesting, but has its dangers. It only buys us a slight optimization by delaying the generation of the forwarders. Note, that the forward command only registers a command and is fairly efficient (comparable with a single eval).
To be complete, yet another approach is to use filter or instfilters, here a filter solution:
Class Queue -array set forwarder {clear 1 get 1 put 1 peek 1 unget 1 size 1} Queue instproc qfilter args { if {[[self class] exists forwarder([self calledproc])]} { return [eval [self]::queue [self calledproc] $args] } next } Queue instproc init {} { ::struct::queue [self]::queue my filter qfilter } Queue instproc destroy {} { [self]::queue destroy next }
-gustaf
ad 1) If we take the example based on unknown and add a mixin, as with this tricky oneliner
Class M -instproc get args next Class Queue -parameter {{queue [self]::queue}} -instmixin M
then the command "get" is defined, therefore "unknown" is not called when "myqueue get" is invoked. Therefore, there will be no forwarding to the queue...