You can do this with something like this:
namespace eval test {}
proc test::set_test_globals {} {
variable variable val
}
If you use
proc test::set_test_globals_a {} {
set test::variable a
}
variable will be created relative to the test namespace, i.e. as ::test::test::variable, provided the ::test::test namespace exists.
proc test::set_test_globals_b {} {
set ::test::variable b
}
Here, using a qualified (absolute) namespace means that regardless of which namespace set_test_globals_b is in, the variable will be created in the ::test namespace.
But there is a dedicated command, variable, which declares or creates variables in the current namespace without any further namespace specification.
proc test::set_test_globals_c {} {
variable variable c
}
Since the command belongs to the ::test namespace (assuming in all cases here that the proc calls are made in the global namespace and not inside any namespace eval scripts), the variable command ensures that the variable variable is created in the same namespace.
Note that you can also invoke the variable command with only the variable name as argument, in which case the variable is declared but does not yet exist.
proc test::set_test_globals_d {} {
variable variable
# variable does not exist here
set variable d
# variable now exists as ::test::variable
}
If variable variable had not been invoked in the last example, set variable d would have created as a local variable instead.
One common idiom is to use one-argument variable invocations inside a namespace eval to document that the namespace contains those variables:
namespace eval test {
variable variable
# variable does not exist yet
}
proc test::set_test_globals_d {} {
variable variable
# variable still does not exist here
set variable d
# ::test::variable now exists with the value d
}
Note that you still need to invoke variable variable again within each command that will use the namespace variable. The first command to assign a namespace variable a value creates it for the whole namespace and all commands that use it.
The name variable is a valid variable name even though there is a variable command, but it's probably less confusing to use another name for the variable.
For completeness, there is a namespace upvar command that creates links between local variables and namespace variables in much the same manner as upvar can do (i.e. namespace upvar $ns a b is almost, but not quite, the same as upvar 0 ${ns}::a b).
Documentation: namespace, proc, set, upvar, variable