variable , a built-in Tcl command since 8.0, declares and optionally sets variables in a namespace.
Declares a variable named name, relative to the current namespace, and binds that variable to the tail of that name in the current evaluation level. $name may be fully-qualified , partially-qualified, or unqualified. If a corresponding value is provided, the variable is set to that value.
name can be the name of an array, but not of a variable in the array.
Where possible, to minimize pollution in the global namespace, it is usually advisable to use variable where one might be tempted to use global
namespace eval one { variable greeting hello } set one::greeting ;#-> hello
A variable may be declared but unset:
namespace which -variable hello; #-> ::hello namespace which -variable goodbye; #-> <the empty string}
In a procedure, variable binds a namespace variable to the same name at the level of the procedure:
proc p1 {} { variable name Priam } p1 ;#-> Priam namespace eval n1 { variable name Hector } namespace eval n2 { proc p2 {} { variable ::n1::name set name } } n2::p2 ;#-> hector
Where one call to global suffices to declare multiple variables,
global foo bar grill
multiple calls to variable are required:
variable foo; variable bar; variable grill
In the following example, namespace which identifies ::bar::a, but within foo::p1, variable resolves to ::foo::bar::a, which doesn't exist:
namespace eval ::bar {variable a 1} namespace eval ::foo { puts [list {bar::a resolves to} [namespace which -variable bar::a]] proc p1 {} { variable bar::a puts $a } } ::foo::p1 ;# -> can't access "bar::a": parent namespace doesn't exist
set looks for an existing variable in the same way namespace which -variable does, and selects and existing variable if available. In contrast, variable just tacks the current namespace onto the provided $name, in order to make it fully qualified.
escargo 2003-09-04: In URL behaviour in a text widget, there are some code idioms I am not familiar with. One of them is:
variable {}
What the heck is that supposed to do?
DGP, PYK: Just what the docs say. It links the variable named [namespace current]:: . Note that namespace tail [namespace current]:: is the empty string.
In this particular case, the variable named the empty string is an array variable, so one can set and read its member variables like so:
set (elem1) 1 set (elem2) 2 if {$(elem1) > $(elem2)} { set greater elem1 } else { set greater elem2 } puts "Greater is $($greater)"
escargo 2003-09-05: Gosh wow. Not only is everything is a string, but nothing is a string. RS: 'Everything' includes 'nothing'...
KJN: 2004-08-12: I came here looking for an explanation of this unusual idiom, and I'm pleased to find it!
I had not realised until now that the minimum number of characters in a name is zero! (Is that mentioned in the manual anywhere?) Even without a variable statement, it is valid to write:
set {} 12 puts ${} ;# -> 12 set {} ;# -> 12
The empty string is an acceptable name for a procedures:
proc {} a { puts $a return $a } {} 42
which echoes 42 to stdout and returns 42.
RS: For scalar variables and commands you still have to delimit the "nothing" with quotes or braces, but with array names, nothing is enough. The Tcl documentation says:
$''name''(index)
name is the name of an array variable and index is the name of an element within that array. Name must contain only letters, digits, underscores, and namespace separators, and may be an empty string. Hence the $(key) syntax DGP explained.
Dossy and Helmut Giese were recently discussing variable on comp.lang.tcl. Dossy replies to a remark by Helmut:
So you have to distinguish between 'creating' a variable and 'defining' it. In your example you _create_ 'foo::bar' but don't _define_ it. Hence [info exist] doesn't see it - as told in the book.
Ahh, yes. Okay, so then the docs and the behavior ARE consistent, cool. I didn't realize that a variable could be "created" but not "exist" -- weird. :-)
PYK 2015-02-28, 2019-10-15: "Declare" is a better word for it than "create". info exists would have been more aptly named info set:
% namespace eval foo { proc foo {} { variable myarr upvar somearr myarr parray myarr } proc foo2 {} { variable myarr namespace which -variable myarr } proc foo3 {} { variable myarr info exists myarr } } % foo::foo "myarr" isn't an array % set somearr(x) y y % foo::foo myarr(x) = y % foo::foo2 ::foo::myarr % foo::foo3 0
m7j4k9 2017-08-25
Currently (8.6.4), the command
variable name
returns nothing, but if it were to return the name, then dudes who are "into the whole brevity thing" could write:
array set [variable foo] { this initializes {} and not foo! }
instead of:
variable foo array set foo { this indeed initializes foo }
which works and intended; unlike:
variable name { this is a dict/list and not an array }
earnie - 2018-06-16 13:58:27
@m7j4k9 I could see perhaps the following syntax for what you propose:
array variable foo {initialize foo}
This would then be in keeping with the same principals as array set combined with the principals of variable.
PYK 2021-07-28: If anything, variable should return the value the variable is set to.