2017-12-18

Ruby-style accessors in TclOO

A way to get Ruby-style accessors in TclOO. Inspired by code on the Tcl Wiki by “anonymous”, improved by Nathan Coulter. This code has been posted to the Wiki as well.

Accessors let you declare instance variables and getter and/or setter methods for them at the same time. The attr_reader and attr_accessor commands declare one or more variables and also methods for them with the same name, which return the current value of the variable. The attr_writer and attr_accessor commands declare one or more variables and also methods for them with the same name with an appended =, which take a value argument and set the variable to that value. So attr_accessor foo bar  declares the variables foo and bar , the getter methods foo and bar , and the setter methods foo= and bar=

namespace eval oo::define {
    proc attr {access args} {
        set class [lindex [info level -1] 1]
        ::oo::define $class variable {*}$args
        if {"reader" in $access} {
            foreach name $args {
                ::oo::define $class method $name {} \
                    [format {set %s} $name]
            }
        }
        if {"writer" in $access} {
            foreach name $args {
                ::oo::define $class method $name= v \
                    [format {set %s $v} $name]
            }
        }
    }
     
    interp alias {} attr_reader {} ::oo::define::attr reader
    interp alias {} attr_writer {} ::oo::define::attr writer
    interp alias {} attr_accessor {} ::oo::define::attr {reader writer}
}

2017-12-17

Defining a callback in Tcl

I have posted this text on the Tcl wiki as well.

Tcl uses the callback protocol for everything from higher-order functions to event-driven programming. As with so many other things Tcl, callbacks are fairly straightforward. Still, some explanation can be useful.

What is a callback?

A callback is "executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at a given time" ([1], [2]).

In some cases, as when a -command option is passed to lsort, the receiving command (see below) immediately executes the code (blocking, or synchronous, callback). More commonly, a callback is specified in an after, bind, trace, I/O handler, or widget -command option, etc, and called when appropriate (event-oriented, deferred, or asynchronous, callback). A deferred callback must be able to execute even if the context where it was defined has since been destroyed.