Tcl Namespaces
Namespaces provide a means of organizing procedures and variables in Tcl.
A global procedure acts just like any function within Tcl. A global procedure can be called from a namespace without any need to import or otherwise localize the procedure. A procedure within a namespace is local to the namespace unless it is explicitly called or the procedure is exported from the namespace. The global scope is also designed such that any variables defined outside of a procedure or a namespace are automatically in the global scope. To access a global variable in a local scope, such as a procedure or namespace, you will need to use the global command. As a script grows and as the number of scripts running simultaneously increases, the ability of the developer to avoid conflict between the names of procedures and variables defined in the global scope decreases.
set f "This is a global variable";
#This procedure cannot access the global variable f.
proc testproc1 { } {
catch {puts $f} val;
puts $val;
}
#This procedure can access the global variable f using the global command.
proc testproc2 { } {
global f;
catch {puts $f} val;
puts $val;
}
testproc1;
can't read "f": no such variable
testproc2;
This is a global variable
Likewise, any variable declared as global from within the procedure where the variable is defined is also included in the global scope, once the procedure has been run. Any attempt to access the variable before running the procedure will cause an error. The upvar command can be used to change the availability of a variable by providing a pointer to the source variable’s contents.
set ::element_list "1 2 3 4 5";
proc ::element_info {} {
puts $::element_list;
set ::node_list "10 20 30 40";
puts $::node_list;
}
element_info;
1 2 3 4 5
10 20 30 40
puts $::element_list;
1 2 3 4 5
puts $::node_list;
10 20 30 40
- namespace eval name {body}
- Used to define a namespace or to run commands inside a namespace.
- namespace current
- Returns the qualified name of the current namespace.
- namespace delete name
- Deletes and existing namespace.
- namespace exists name
- Check for the existence of a namespace.
- variable name ?value?
- Used to define, and optionally assign a value to, a variable within a namespace.
namespace eval ::my_namespace {
variable element_list "1 2 3 4 5";
}
proc ::my_namespace::element_info {} {
variable element_list;
puts $element_list;
variable node_list "10 20 30 40";
puts $::node_list;
}
::my_namespace::element_info;
1 2 3 4 5
10 20 30 40
puts $::my_namespace::element_list;
1 2 3 4 5
puts $::my_namespace::node_list;
10 20 30 40
#Script begins.
#Define a variable in the global scope.
set f "This is a global variable";
#This global procedure will generate an error because the
#global variable f is not in the scope.
proc testproc1 {} {
catch {puts $f} g;
puts $g;
}
#This procedure will not generate an error because the
#global variable f is localized with the global command.
proc testproc2 {} {
global f;
catch {puts $f} g;
puts $g;
}
#A call to delete the namespace clears variables within
#that namespace.
catch {namespace delete ::testspace};
#The namespace eval command creates a new namespace.
namespace eval ::testspace {
variable fg "This is a namespace variable";
#Export a single procedure for use later.
namespace export tproc3
}
#Procedures can be organized into namespaces.
proc ::testspace::tproc1 {} {
#Global procedures do not require a namespace indicator.
testproc1;
testproc2;
#Procedures within the same scope do not require a
#namespace indicator.
tproc2;
tproc3;
#Procedures from other namespaces must be explicitly declared
#unless a namespace import is used.
catch {oproc1} ds;
puts $ds;
::otherspace::oproc1;
}
#This namespace procedure will generate an error because the
#namespace variable is not in the scope.
proc ::testspace::tproc2 {} {
#The catch command is used to prevent the script from
#exiting with an error.
catch {puts $fg} g;
puts $g;
}
#This namespace procedure will not generate an error because the
#namespace variable is localized.
proc ::testspace::tproc3 {} {
#The variable command, if referring to an existing
#namespace variable and not making an assignment,
#allows local access to the variable.
variable fg;
catch {puts $fg} g;
puts $g;
}
#A call to delete the namespace clears variables within
#that namespace.
catch {namespace delete ::otherspace};
#Creating a second namespace.
namespace eval ::otherspace {
variable fh "This is a different namespace variable";
}
proc ::otherspace::oproc1 {} {
#The namespace import command can be used to
#localize procedures.
namespace import ::testspace::tproc3;
variable fh;
catch {puts $fh} h;
puts $h;
tproc3;
#namespace origin returns original namespace of the proc.
puts [namespace origin tproc3];
}
#Run the primary procedure
::testspace::tproc1
can't read "f": no such variable
This is a global variable
can't read "fg": no such variable
This is a namespace variable
invalid command name "oproc1"
This is a different namespace variable
This is a namespace variable
::testspace::tproc3