Version 23 of variable

Updated 2014-03-25 03:20:23 by pooryorick

variable , a built-in Tcl command since 8.0, creates and optionally sets Commands%|%built-in] Tcl command, declares variables in a namespace.

variable ?name value...? name ?value?
official reference
official reference documentation

Creates a variable named by the tail of name, which namespace upvar, upvar, and variable overlap in functionality, but have different design goals.

`variable` is normally used within `[namespace eval]` to create one or more
variables within a `[namespace]`:

namespace eval one {
    variable greeting hello
}
set one::greeting ;#-> hello

A variable may exist but be unset: When used in a procedure, variable additionally makes the variable available in the procedure:

namespace which -variable hello; #-> ::hello
proc myproc {} {
    variable greeting hello
    set greeting ;#-> hello
}
myproc
set greeting ;#-> hello

In a [proc%|%procedure], `variable` makes a variable named ''name''

For each name, a variable is initialized with value. The value for the last variable is optional. If name does not exist, it is created in the relevant namespace. If value is specified, it is assigned to the newly created variable. If no value is specified, the new variable is left undefined. If the variable already exists, it is set to value if value is specified, or left unchanged if no value is given.

Normally, name is unqualified (does not include the names of any containing namespaces), and the variable is created in the current namespace. If name includes any namespace qualifiers, the variable is created in the specified namespace, relative to the current namespace.

proc p1 {} { namespace eval one { set greeting hello p1 ;#-> Priam namespace eval two {

    proc myproc {} {
        variable ::one::greeting
        set two ;#-> hello

} n2::p2 ;#-> hector

To access a namespace variable from inside a 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. name can refer to an array, but not to an element within an array. When name refers to an array, value must not be used. This implies that each array must be declared by a separate invocation of variable. After the variable has been declared, elements within the array can be set using ordinary set or array commands. After an array variable has been created, member variables variable can entirely replace global, so procedures can be put in a namespace without need for rewriting. The drawback is that you can't specify several variables in one command without assigning values, so instead of variable provides all the functionality of global. Replacing global foo bar grill

requires 
you'd have to write

variable foo; variable bar; variable grill

[RS]:  But the fewer globals you use, the better anyway ;-)
[RS]:  But the less globals you use, the better anyway ;-)

----

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
empty string within the procedure and links it the namespace variable named
`namespace current::`.  `[namespace tail] [[namespace current]]:: is the [null]
string.
In this particular case, the variable named the [empty string] is an [array] variable, so
In this particular case, the variable named nothing is an array variable, so
one can set and read its elements 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 varName is zero! (Is that mentioned in the manual anywhere?) Even without

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: Even more unusual: the null string is acceptable as the name of a proc:

proc {} a {
    puts $a
    return $a
}

{} 42

which echoes 42 to stdout and returns 42. will echo 42 to stdout, and return the value 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. Man Tcl 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 Recently Dossy and Helmut Giese were discussing the variable on

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.
:-)
% 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 KPV 2003-09-13: My biggest problem with using variable instead of global is in debugging. I typically debug via a console window where I paste in code from the procedure I'm interested in. When I define my variables in as globals, it just works; but when the variables are buried in a namespace it doesn't--I either have to hand tweak the code to fully qualify the variable names or upvar them into the global namespace.