Callbacks and Namespaces

   

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 14.  Namespaces


graphics/tip_icon.gif

Commands like after, bind, and button take arguments that are Tcl scripts that are evaluated later. These callback commands execute later in the global scope by default. If you want a callback to be evaluated in a particular namespace, you can construct the callback with namespace code. This command does not execute the callback. Instead, it generates a Tcl command that will execute in the current namespace scope when it is evaluated later. For example, suppose ::current is the current namespace. The namespace code command determines the current scope and adds that to the namespace inscope command it generates:

 set callback [namespace code {set x 1}] => namespace inscope ::current {set x 1} # sometime later ... eval $callback 

When you evaluate $callback later, it executes in the ::current namespace because of the namespace inscope command. In particular, if there is a namespace variable ::current::x, then that variable is modified. An alternative to using namespace code is to name the variable with a qualified name:

 set callback {set ::current::x 1} 

The drawback of this approach is that it makes it tedious to move the code to a different namespace.

If you need substitutions to occur on the command when you define it, use list to construct it. Using list is discussed in more detail on pages 123 and 389. Example 14-4 wraps up the list and the namespace inscope into the code procedure, which is handy because you almost always want to use list when constructing callbacks. The uplevel in code ensures that the correct namespace is captured; you can use code anywhere:

Example 14-4 The code procedure to wrap callbacks.
 proc code {args} {    set namespace [uplevel {namespace current}]    return [list namespace inscope $namespace $args] } namespace eval foo {    variable y "y value" x {}    set callback [code set x $y]    => namespace inscope ::foo {set x {y value}} } 

The example defines a callback that will set ::foo::x to y value. If you want to set x to the value that y has at the time of the callback, then you do not want to do any substitutions. In that case, the original namespace code is what you want:

 set callback [namespace code {set x $y}] => namespace inscope ::foo {set x $y} 

If the callback has additional arguments added by the caller, namespace inscope correctly adds them. For example, the scrollbar protocol described on page 431 adds parameters to the callback that controls a scrollbar.


       
    Top
     



    Practical Programming in Tcl and Tk
    Practical Programming in Tcl and Tk (4th Edition)
    ISBN: 0130385603
    EAN: 2147483647
    Year: 1999
    Pages: 478

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net