[SS]: An interesting object-oriented programming language; basic ideas come from [SmallTalk] but SELF is more flexible and powerful, and probably even more ''pure''. SELF was used as test-bed for new ideas about compilation and virtual machines of very-high-level programming languages. More info at [http://research.sun.com/self/language.html] and [http://www.objs.com/x3h7/self.htm]. It should be possible to build an object-system for [Tcl] that uses ideas from SELF; maybe it was already implemented. Please, if you know more, or have some code to show, write it here. [RS] wrote [On things], which might interest you. [SS] - great! it is pretty similar to SELF, I like the design [RS] used to add it to TCL. [Artur Trzewik] - Some of SELF ideas are also included in [XOTcl]; that are mixins. Also in XOTcl the object has relative more importance than class. Classes are also objects and the relationship between objects and classes is dynamic. Self is prototype-based OO language, but some programing technigues one can be well-simulated with XOTcl mixins and filters. The manner of how to program with SELF is also implemented in [XOTclIDE]. That is interatively extent or change running, "living" system. The same way Smalltalkers program. [SS]: I see a fundamental difference between [SELF] and [XOTcl] btw: [SELF] is simple; there is even no difference between a method and instance variable, everything is a slot, and there are many other simplifications like no classes at all. On the exact contrary [XOTcl] has a lot of concepts, so I think the essence is very different, while of course with every kind of OO-related feature you can fake the coding way of prototype-based systems, class-based systems, and so on. [KBK] 2006-10-12: One of the earliest OO systems for TCL, [BOS], was consciously modelled after [Self]. Developed by Sean Levy, then of CMU, it had several other interesting ideas. A description can be found at http://www.ndim.edrc.cmu.edu/papers/bos.pdf ; the paper also discusses Sean's reasons for abandoning Tcl in the implementation. The original Tcl implementation is at ftp://ftp.procplace.com/pub/tcl/sorted/packages-7.6/devel/bos-1.31.tar.gz . ---- [MJ] -- Basic implementation of a self-like OO system in plain Tcl. Supports '''super''', '''self''' and '''slot''' in slot bodies. If a slot cannot be found, the unknown slot is called on the object receiving the message. [MJ] -- The Tcl implementation below has problems when calls to next or self are chained. The C extension at [SELF extension] doesn't have these problems. # parents* for method dispatch namespace eval self { set Object(parents*) {data {}} set Object(slot) {method { {name args} { # value slot if {[llength $args]==1} { set value [lindex $args 0] set ::self::[self]($name) [list data $value] return $name } elseif {[llength $args]==2} { # method slot set arguments [lindex $args 0] set body [lindex $args 1] set ::self::[self]($name) [list method [list $arguments $body]] return $name } else { error "wrong number of args: use slot name value/args ?body?" } } } } } proc ::self::selfcmd {self args} { if {$args eq ""} { return $self } $self {*}$args } proc Object {args} { set self [lindex [info level 0] 0] set slot [lindex $args 0] set old_self [interp alias {} self] interp alias {} self {} ::self::selfcmd $self set slot_value {} if {[llength $args]==0} {return $self} if {[info exists ::self::${self}($slot)]} { set slot_value [set ::self::${self}($slot)] } else { set ancestors [$self parents*] set visited {} while {true} { set obj [lindex $ancestors 0] if {[llength $obj]==0} { break } # keep a visited objects list to prevent circular lookups if {[lsearch -exact $visited $obj]>-1} { set ancestors [lrange $ancestors 1 end] continue } lappend visited $obj catch {set ancestors [list {*}[lrange $ancestors 1 end] {*}[$obj parents*]]} if {[info exists ::self::${obj}($slot)]} { set slot_value [set ::self::${obj}($slot)] } } } if {$slot_value ne {}} { switch [lindex $slot_value 0] { method { set res [apply [lindex $slot_value 1] {*}[lrange $args 1 end]] } data { if {[llength $args]==1} { set res [lindex $slot_value end] } else { self slot [list data [lindex $args 2]] set res [self] } } } interp alias {} self {} {*}$old_self return $res } else { interp alias {} self {} {*}$old_self error "object '$self' can't handle slot '$slot'" } } set ::self::Object(clone) [list method {{new} { # we need the parent slot before we can do any method dispatch set ::self::[set new](parents*) [list data [self]] proc $new args [info body Object] return $new }}] set ::self::Object(slot) [list method [list {name args} { if {[llength $args]==2} { set ::self::[self]($name) [list method $args] } else { set ::self::[self]($name) [list data [lindex $args 0]] } return [self] }]] Object slot destroy {} { unset ::self::[self] rename [self] {} } Object slot slots {} { return [lsort [array names ::self::[self]]] } package provide self 0.2 ---- [MJ] - See [Self on a class-based OO system] for a partial implementation of Self using the tip 257 OO extension, or "Basis for a Self like OO system based on coroutines" [http://paste.tclers.tk/1455] for ... well, for just what it says. ---- [MJ] - Inclusion of [coroutine]s in Tcl 8.6 opens another avenue of approach to implement Self in plain Tcl. It seems an object and a coroutine share some common characteristics making coroutines a good fit to implement OO (this is probably evident for all you CS majors, but it was a bit of a revelation to me). I can see at least two things that should be added to coroutines for this to be feasible: * ability to yield an error (possibly with -level to create nice error messages in the same manner as return) * ability to call the coro with arbitrary # args (yield will always return a list) A short example of what this could look like is: proc _object {args} { set next [lindex $args 0] while {$next ne "destroy"} { # actual dispatch loop will be here switch [lindex $next 0] { parents* { set res "" } clone { coroutine Object2 _object set res Object2 } "" { set a 4 set res ok } } set next [yield $res] } } coroutine Object _object Object parents* Object clone Object destroy Object sadas This seems to be a dead avenue of approach, because you can't call a coroutine from within itself. This seems to make it impossible to call other object slots from with object slots. ---- [[[Category Language]|[Category Object Orientation]]]