namespacestclvariable-assignment

'set' vs 'variable' in Tcl


afaik, there are two ways two create and assign a namespaced variable in Tcl:

namespace eval ::myspace:: {
  variable foo 1
}
set ::myspace::bar 2

afaict, the two are equivalent:

info vars ::myspace::*
# ::myspace::foo ::myspace::bar

I have wondered for a while, whether they are really equivalent (and which one is the preferred form).


Solution

  • The set command is a basic operation. If you give it two arguments, it resolves the variable with the name typically preferring a local variable over anything else) and writes the value to the variable, returning the contents of the variable. (Usuallly the same thing as the value you wrote.) With one argument it reads the variable instead.

    The variable command ensures that that name will resolve to the variable with that name in the current namespace; in a context with local variables (inside a procedure or method) it makes a link from the local variable with that name to the resolved namespace variable. And can write a simple variable too, if you supply a value. It can process multiple variables... but I don't use that much. It has an empty result.

    If you use a fully-qualified variable name with set, you can write any namespace variable directly. It's just a different way of looking up the underlying reality; variables are not their names, after all, a name is just a way to find a variable.

    The linking mechanism is also used by global, upvar and namespace upvar. It is very fast (after formation), typically involving a single extra deference in the bytecode engine.