variable vs global

This example illustrates difference of precedence by resolving of not fully-qualified namespace variables in procedure using variable and global.

The test creates several nested namespaces and uses procedure tv acquiring the variable using supplied arguments, testing its access and finally output the access-method, the var-name and namespace where it is called from and the value of variable (or error if it unresolvable).

So ::P::C::tv global P::v tries to access NFQ variable P::v from procedure of namespace ::P::C using global, whereas ::P::C::tv variable P::v does the same using variable.

The test calling it 4 times is repeated twice (without and with additional nested namespaces/variables).

variable v "::v"
namespace eval ::P {
  proc tv {h n} { puts -nonewline [format "%.4s %4s from %-7s ->   " $h $n [namespace current]]; catch { $h $n; set v } res; puts $res }
  variable v "[namespace current]::v";
  namespace eval C {
    variable v "[namespace current]::v";
    proc tv {h n} [info body ::P::tv]
  }
}
proc test {ns} {
  puts "  ================  test $ns   === "
  namespace eval $ns {
    tv global   P::v
    tv variable P::v
    tv global   v
    tv variable v
  }
}

puts "================== without ::P::P::v and ::P::C::P::v =================="
test ::P::C; test ::P

puts "================== create ::P::P::v and ::P::C::P::v =================="
foreach n {::P::C::P ::P::P} {
  namespace eval $n {  variable v "[namespace current]::v" }
}

test ::P::C; test ::P

results in:

================== without ::P::P::v and ::P::C::P::v ==================
  ================  test ::P::C   ===
glob P::v from ::P::C  ->   ::P::v
vari P::v from ::P::C  ->   can't define "P::v": parent namespace doesn't exist
glob    v from ::P::C  ->   ::v
vari    v from ::P::C  ->   ::P::C::v
  ================  test ::P   ===
glob P::v from ::P     ->   ::P::v
vari P::v from ::P     ->   can't define "P::v": parent namespace doesn't exist
glob    v from ::P     ->   ::v
vari    v from ::P     ->   ::P::v
================== create ::P::P::v and ::P::C::P::v ==================
  ================  test ::P::C   ===
glob P::v from ::P::C  ->   ::P::v
vari P::v from ::P::C  ->   ::P::C::P::v
glob    v from ::P::C  ->   ::v
vari    v from ::P::C  ->   ::P::C::v
  ================  test ::P   ===
glob P::v from ::P     ->   ::P::v
vari P::v from ::P     ->   ::P::P::v
glob    v from ::P     ->   ::v
vari    v from ::P     ->   ::P::v

See Also

variable
Declares and optionally sets variables in a namespace.
global
Access global variables or variables in a namespace.
set
Reads or assigns a value to a variable.
namespace upvar
Gives a variable in one namespace a name at the current level.
upvar
Links a variable at some higher level to a variable at the current level.