'''[http://www.tcl.tk/man/tcl/TclCmd/variable.htm%|%variable]''', a [Tcl Commands%|%built-in] [Tcl] [command] since [Changes in Tcl/Tk 8.0%|%8.0], creates and optionally [set%|%sets] Commands%|%built-in] [Tcl] [command], creates and optionally [set%|%sets] ** See Also ** `[set]`: Reads or assigns a value to a variable. `[set]`: reads or assigns a value to a variable. `[namespace upvar]`: Gives a variable in one namespace a name in another. `[namespace upvar]`: links a variable in a namespace to another variable `[upvar]`: Gives a variable at one level of evaluation a name in another. `[upvar]`: links a variable at one level of evaluation to another variable [Variables in TclOO]: Discusses `variable`, `[oo::define] variable`, `[oo::objdefine] variable` and `[my] variable` in [TclOO] ** Synopsis ** : '''variable''' ?''name value...''? ''name'' ?''value''? ** Documentation ** [http://www.tcl.tk/man/tcl/TclCmd/variable.htm%|%official reference]: ** Description ** Creates a variable named by the `[namespace tail%|%tail]` of ''name'', which For each ''name'', `[variable]` resolves ''name'' relative to the [namespace current%|%current namespace] and creates a variable by that name if it doesn't already exist. If a corresponding ''value'' is provided, the variable is [set] to that value. ====== namespace eval one { variable greeting hello } set one::greeting ;#-> hello ====== A variable may exist but be unset: ====== namespace which -variable hello; #-> ::hello namespace which -variable goodbye; #-> Priam namespace eval n1 { variable name Hector } namespace eval n2 { proc p2 {} { variable ::n1::name set name } } n2::p2 ;#-> hector ====== To access a namespace variable from inside a [proc%|%procedure], declare it using `variable`. In this way `variable` resembles `[global]`, but `[global]` is restricted to variables in the global namespace. ''name'' can refer to an [array], but not to a variable in the array. Therefore, when ''name'' refers to an array, ''value'' must not be used. This Terefore, when ''name'' refers to an array, ''value'' must not be used. This `[variable]`. After an array variable has been created, member variables within the array using `[set]` or `[array]`. `[variable]` provides all the functionality of `[global]`. Replacing `[global]` with `[variable]` within a procedure is often all that's needed when moving a procedure from the global namespace to another namespace. In contrast with `[global]`, the syntax of `[variable]` sometimes makes it necessary to have a sequence of `variable` commands within a procedure. To replace ====== global foo bar grill ====== requires ====== variable foo; variable bar; variable grill ====== [RS]: But the fewer globals you use, the better anyway ;-) ** An Asymmetry with `[namespace which]` ** In the following example, `[namespace which]` identifies `::bar::a`, but within `foo::p1`, `[variable]` resolves to `::foo::bar::a`, which doesn't withing `foo::p1`, `[variable]` resolves to `::foo::bar::a`, which doesn't ====== namespace eval ::bar {variable a 1} namespace eval ::foo { puts [list {bar::a resolves to} [namespace which -variable bar::a]] namespace which -variable bar::a variable bar::a puts $a } } ====== `[namespace which] -variable` looks up variables in the same way that `[set]` does, whereas `[variable]` resolves a name relative to the current namespace, without looking to the [global] namespace like `[set]` may do. `[namespace which -variable]` looks up variables in the same way that `[set]` does, whereas `[variable]` resolves a name relative to the current namespace, without looking to the [global] namespace like `[set]` may do. ** Discussion ** [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]: Just what the docs say. It creates a local variable whose name is the empty string within the procedure and links it to the namespace 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 ${} set {} ====== This code will echo `12` to stdout, and return the value `12`. The [empty string] is an acceptable name for a [proc]: ====== proc {} a { puts $a return $a } {} 42 ====== which echoes `42` to [stdout] and [return%|%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: 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 and namespace separators, '''and may be an [empty string]'''. - Hence the ---- [Dossy] and [Helmut Giese] were recently discussing `[variable]` on [comp.lang.tcl]. Dossy replies to a remark by Helmut: ======none 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. ====== ======none 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: `[info exists]` would have been more aptly named `info [PYK] 2015-02-28: `[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 foo::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 ====== ---- Currently (8.6.4), the command