Why does the variable command Tcl always return an empty string?


See code below:

namespace eval foo {
    variable bar 5
    proc getBar {} {
    variable bar
    proc getRetBar {} {
    variable bar
    return $bar
puts "\"[ foo::getBar ]\""
puts "\"[ foo::getRetBar ]\""

It outputs:


Why does it not return the variable value, just like the set command would? Why does it always return an empty string? If I want to access namespace variables through procedure, and not by accessing them directly, it makes the code slightly longer. Not a major issue, but a little annoying

That's the way the command is defined. It makes sense, because if given an odd number of arguments, the last one is a name that will be declared as a namespace variable but need not exist. If it doesn't exist, what value should variable return?

Still, it's no hassle to write a single-command getter procedure (assuming the variable exists):

proc getBar {} {
    set [namespace current]::bar

Or you could use a TclOO object (note that you need a setter to initialize it):

oo::object create foo
# -> ::foo
oo::objdefine foo variable bar
oo::objdefine foo method setBar v {set bar $v}
oo::objdefine foo method getBar {} {set bar}
foo setBar 5
# -> 5
puts "\"[foo getBar]\""
# => "5"

You can define the object in one call, if you prefer:

oo::objdefine foo {
    variable bar
    method setBar v {set bar $v}
    method getBar {} {set bar}

Documentation: namespace, oo::objdefine, oo::object, variable