Version 2 of Dangers of creative writing

Updated 2001-11-13 20:28:54

Richard Suchenwirth - "Creative writing" in this context means assigning a value (writing) to a variable referred to by name, that is created if it doesn't exist. The following Tcl commands are "creative writers": array set - foreach - gets - lappend - regexp - regsub - scan - set

When code is evaluated in a namespace, but outside of a proc, the namespace rule for name resolution applies: If you provide a fully-qualified name that starts with a ::, there is no question about what command, variable, or namespace you mean. However, if the name does not start with a :: (i.e., is relative), Tcl follows a fixed rule for looking it up: Command and variable names are always resolved by looking first in the current namespace, and then in the global namespace. (TclHelp, namespace man page)

This leads to dangerous context-dependency: depending on what global variables exist, new variables are created either here or there. Ronnie Brunner wrote in the comp.lang.tcl newsgroup:

 % set a "global"
 global
 % namespace eval foo {set a "namespace"; set b "namespace"}
 namespace
 % set a
 namespace
 % set foo::a
 can't read "foo::a": no such variable
 % set b
 can't read "b": no such variable
 % set foo::b
 namespace

Hemang Lavana commented: To be safe, you should always use the `variable' command first to declare a variable in the current namespace.

RS: But still, this requirement for a declaration is not in the spirit of Tcl.

Proc definitions inside a namespace remain in that namespace, however; they don't go out to the global namespace, as Ronnie further showed:

 % proc a {} {puts global}
 % namespace eval foo {proc a {} {puts namespace};proc b {} {puts namespace}}
 % a
 global
 % foo::a
 namespace
 % b
 ambiguous command name "b": binary break
 % foo::b
 namespace

RS: I think namespace resolution should distinguish between locating existing things (procs or variables) and determining an absolute name for non-existing things.

  • For locating existing things, the current resolution rule can be left unchanged.
  • For "creative writing", creating new things, it should confine itself to the current namespace (as it currently does with procs). He who wants something done in the global namespace, can explicitly prepend :: to the name ;-)

Arts and crafts of Tcl-Tk programming