namespace ?subcommand? ?arg ...?
Extensions like Tk normally execute callback scripts in the global namespace. A scoped command captures a command together with its namespace context in a way that allows it to be executed properly later. See the section SCOPED VALUES for some examples of how this is used to create callback scripts.
If a namespace eval command creates a new namespace name,
then name determines its parent namespace and
the new namespace's position in the hierarchy of namespaces.
If name includes a sequence of namespace qualifiers
separated by ::s,
it is created as a child of the specified parent namespace;
otherwise, the namespace is created as a child of the current namespace.
If name has leading namespace qualifiers
and any leading namespaces do not exist,
they are automatically created.
namespace eval is another way (besides procedure calls) that the Tcl naming context can change. It adds a call frame to the stack to represent the namespace context. This means each namespace eval command counts as another call level for uplevel and upvar commands. For example, info level 1 will return a list describing a command that is either the outermost procedure call or the outermost namespace eval command. Also, uplevel #0 evaluates a script at top-level in the outermost namespace (the global namespace).
creates a new namespace containing the variable num and the procedure Bump. The commands and variables in this namespace are separate from other commands and variables in the same program. If there is a command named Bump in the global namespace, for example, it will not interfere with the command Bump in the Counter namespace.namespace eval Counter { namespace export Bump variable num 0 proc Bump {} { variable num incr num } }
Namespace variables resemble global variables in Tcl. They exist outside of the procedures in a namespace but can be accessed in a procedure via the variable command, as shown in the example above.
Namespaces are dynamic. You can add and delete commands and variables at any time. So you can build up the contents of a namespace over time using a series of namespace eval commands. For example, the following series of commands has the same effect as the namespace definition shown above:
Note that the test procedure is added to the Counter namespace, and later removed via the rename command.namespace Counter { variable num 0 proc Bump {} { variable num return [incr num] } } namespace Counter { proc test {args} { return $args } } namespace Counter { rename test "" }
Namespaces can have other namespaces within them, so they nest hierarchically. A nested namespace is encapsulated inside its parent namespace and can not interfere with other namespaces. If namespaces are used to represent packages, this feature lets one package contain its own copy of another package.
procedures like Bump and Reset execute in the context of namespace Counter.namespace Counter { namespace export Bump Reset variable num 0 proc Bump {{by 1}} { variable num return [incr num $by] } proc Reset {} { variable num set num 0 } }
In this context, you can access the commands and variables that reside in the namespace using simple names. In the example above, we access the num variable with the command variable num. (We can't use global num since that would only look up num in the global namespace.) We can access the Bump and Reset procedures in another procedure like this:
This is the real benefit of namespaces. The commands and variables in a namespace fit together as a module.namespace Counter { namespace export Rebump proc Rebump {{by 1}} { Reset Bump $by } }
If you want to access commands and variables from another namespace, you must use some extra syntax. Names must be qualified by the namespace that contains them. The :: string acts as a separator between the various qualifiers in a name. From the global namespace, we might access the Counter procedures like this:
We could access the current count like this:Counter::Bump 5 Counter::Reset Counter::Rebump 10
When one namespace contains another, you may need more than one qualifier to reach its elements. If we had a namespace Foo that contained the namespace Counter, you could invoke its Bump procedure from the global namespace like this:puts "count = $Counter::num" set Counter::num 35
You can think of namespaces like directories in a file system. When you are sitting in a particular directory context, you can access files with simple names. But from another context, you must use a proper path name. A name like Foo::Counter::Bump is just like a file name Foo/Counter/Bump, except that we have used :: instead of / as the separator. Just as the file system has a root directory /, all namespaces are rooted in the global namespace named ::. So all names can be given with an absolute path that begins with ::. For example, we can say:Foo::Counter::Bump 3
With this name, you can be sure that you'll get the Bump procedure in the Counter namespace, in the Foo namespace, in the global namespace-no matter what the current namespace context may be.::Foo::Counter::Bump 3
You can also use qualified names when you create and rename commands. For example, you could add a procedure to the Foo namespace like this:
And you could move the same procedure to another namespace like this:proc Foo::Test {args} {return $args}
rename Foo::Test Bar::Test
There are a few remaining points about qualified names that we should cover. :: is disallowed in both simple command and variable names except as a namespace separator. Extra :s in a qualified name are ignored; that is, two or more :s are treated as a namespace separator. A trailing :: in a qualified variable or command name refers to the variable or command named {}. However, a trailing :: in a qualified namespace name is ignored.
In the following example,
Tcl looks for traceLevel in the namespace Debug and then in the global namespace. It looks up the command printTrace in the same way. If a variable or command name is not found in either context, the name is undefined. To make this point absolutely clear, consider the following example:set traceLevel 0 namespace Debug { printTrace $traceLevel }
Here Tcl looks for traceLevel first in the namespace Foo::Debug. Since it is not found there, Tcl then looks for it in the global namespace. The variable Foo::traceLevel is completely ignored during the name resolution process.set traceLevel 0 namespace Foo { variable traceLevel 3 namespace Debug { printTrace $traceLevel } }
You can use the namespace which command to clear up any question about name resolution. For example, the command:
returns ::traceLevel. On the other hand, the command,namespace Foo::Debug {namespace which -variable traceLevel}
returns ::Foo::traceLevel.namespace Foo {namespace which -variable traceLevel}
Although Tcl always follows the ``look in the current then in the global namespace'' rule for variables and commands, there is a question of how to resolve a qualified name like foo::bar::cmd. A relative name like this might resolve to either [namespace current]::foo::bar::cmd or to ::foo::bar::cmd. If cmd does not appear in [namespace current]::foo::bar but does appear in ::foo::bar, Tcl assumes it refers to the latter command.
As mentioned above, namespace names are looked up differently than the names of variables and commands. Namespace names are always resolved in the current namespace. This means, for example, that a namespace eval command that creates a new namespace always creates a child of the current namespace unless the new namespace name begins with a ::.
Tcl has no access control to limit what variables, commands, or namespaces you can reference. If you provide a qualified name that resolves to an element by the name resolution rule above, you can access the element.
You can access a namespace variable within a procedure in the same namespace by using the variable command. Much like the global command, this creates a local link to the namespace variable. If necessary, it also creates the variable in the current namespace and initializes it. Note that the global command only creates links to variables in the global namespace. It is not necessary to use a variable command if you always refer to the namespace variable using an appropriate qualified name.
If you use the graph and table commands frequently, you may want to access them without the Blt:: prefix. You can do this by importing the commands into the current namespace, like this:Blt::graph .g -background red Blt::table . .g 0,0
This adds all commands from the Blt namespace into the current namespace context, so you can write code like this:namespace import Blt::*
Importing every command from a namespace is generally a bad idea since you don't know what you will get. It is better to import just the specific commands you need. For example, the commandgraph .g -background red table . .g 0,0
imports only the graph and table commands into the current context.namespace import Blt::graph Blt::table
The namespace import command has snapshot semantics: that is, only requested commands that are currently defined in the exporting namespace are imported. In other words, you can import only the commands that are in a namespace like Blt at the time when the namespace import command is executed. If another command appears in this namespace later on, it will not be imported.
If you try to import a command that already exists, you will get an error. This prevents you from importing the same command from two different packages. But from time to time (perhaps when debugging), you may want to get around this restriction. You may want to reissue the namespace import command to pick up new commands that have appeared in a namespace. In that case, you can use the -force option, and existing commands will be silently overwritten:
If for some reason, you want to stop using the imported commands, you can remove them with an import forget command, like this:namespace import -force Blt::graph Blt::table
This searches the current namespace for any commands imported from Blt. If it finds any, it removes them. Otherwise, it does nothing. After this, the Blt commands must be accessed with the Blt:: prefix.import forget Blt::*
When you delete a command from the exporting namespace like this:
the command is automatically removed from all namespaces that import it.rename Blt::graph ""
The procedures Bump and Reset are exported, so they are included when you import from the Counter namespace, like this:namespace Counter { namespace export Bump Reset variable num 0 variable max 100 proc Bump {{by 1}} { variable num incr num $by check return $num } proc Reset {} { variable num set num 0 } proc check {} { variable num variable max if {$num > $max} { error "too high!" } } }
However, the check procedure is not exported, so it is ignored by the import operation.namespace import Counter::*
The namespace import command only imports commands that were declared as exported by their namespace. The namespace export command specifies what commands may be imported by other namespaces. If a namespace import command specifies a command that is not exported, the command is not imported.
namespace Foo { variable v 123 proc report {msg} { puts "$msg" } after 2000 [namespace code {report "Hello World, v = $v"}] }
Copyright © 1989-1994 The Regents of the University of California.
Copyright © 1994-1997 Sun Microsystems, Inc.