See http://www.purl.org/tcl/home/man/tcl8.5/TclCmd/namespace.htm for the latest release documentation . : '''[namespace children]''' ''?namespace? ?pattern?'' : '''[namespace code]''' ''script'' : '''[namespace code]''' ''script'' : '''[namespace current]''' : '''[namespace current]''' : '''[namespace delete]''' ''?namespace namespace ...?'' : '''[namespace delete]''' ''?namespace namespace ...?'' : '''[namespace ensemble]''' ''option ?arg ...?'' : '''[namespace ensemble]''' ''option ?arg ...?'' : '''[namespace eval]''' ''namespace arg ?arg ...?'' : '''[namespace eval]''' ''namespace arg ?arg ...?'' : '''[namespace exists]''' ''namespace'' : '''[namespace exists]''' ''namespace'' output: : '''[namespace export]''' ''?-'''''clear'''''? ?pattern pattern ...?'' ====== : '''[namespace forget]''' ''?pattern pattern ...?'' From 8.5 onwards, use this instead: : '''[namespace import]''' ''?-'''''force'''''? ?pattern pattern ...?'' ====== : '''[namespace inscope]''' ''namespace script ?arg ...?'' : '''[namespace origin]''' ''command'' list the variables in a namespace: : '''[namespace parent]''' ''?namespace?'' ====== : '''[namespace path]''' ''?namespaceList?'' list the procs in a namespace: : '''[namespace qualifiers]''' ''string'' : '''[namespace tail]''' ''string'' : '''[namespace upvar]''' ''namespace otherVar myVar ?otherVar myVar ...?'' : '''[namespace unknown]''' ''?script?'' : '''[namespace which]''' ''?-'''''command'''''? ?-'''''variable'''''? name'' ---- Also highly recommended is [William Duquette]'s tutorial [http://www.wjduquette.com/tcl/namespaces.html] on the use of namespaces and packages. The "XML Namespaces FAQ" [http://www.rpbourret.com/xml/NamespacesFAQ.htm] has valuable background information on the general use of namespaces in computing, and [Sam Ruby] provides "A Gentle Introduction to Namespaces" [http://www.intertwingly.net/stories/2002/09/09/gentleIntroductionToNamespaces.html] for the [XML]-focused. See also [_namespace import_ and _rename_] to appreciate the extraordinary freedom won through the use of namespaces. ====== ---- list the commands in a namespace: **Introspection** and namespaces: Can someone discuss how a Tcl script can determine: * what namespaces are available at any particular point in time * what procs and variables available in any one of these namespaces Some simple proc to get all child namespaces recursively as a list: ====== proc listns {{parentns ::}} { set result [list] foreach ns [namespace children $parentns] { eval lappend result [listns $ns] lappend result $ns } return $result } % namespace eval ::test {set foo 1} 1 % namespace eval ::test2 {set foo 1} 1 % namespace eval ::test::test3 {set foo 1} 1 % listns ::test::test3 ::test ::test2 ::tcl ====== From 8.5 onwards, use this instead: ====== proc listns {{parentns ::}} { set result [list] foreach ns [namespace children $parentns] { lappend result {*}[listns $ns] $ns } return $result } ====== '''Trivial procs''' for getting variables, procs and commands defined inside a namespace: ====== proc listnsvars {{ns ::}} { return [info vars ${ns}::*] } proc listnsprocs {{ns ::}} { return [info procs ${ns}::*] } proc listnscommands {{ns ::}} { return [info commands ${ns}::*] } ====== They only work well with fully qualified namespace names. Beware that in some apps these may take a long time to complete (for example, if there are hundreds of thousands of commands in ::). <> [LV] 2007 Aug 23 How would one introspectively interact with a namespace to determine what that namespace contains? That is, what procs, variables, or other namespaces reside within a namespace? ''[escargo]'' - See the '''Trivial procs''' above. You use '''namespace children''' to look through the tree of namespaces, and '''info procs''', etc., with namespace qualifiers to look for definitions in each namespace. <> ---- **Variables** '''Re-entering a namespace:''' Inside a ''namespace eval'' body, all namespace variables are visible at first. Inside a proc in the ''namespace eval'' body, they are hidden and must be explicitly made visible with the [variable] command. However, it is possible inside a namespace to re-enter that same namespace by just saying ====== namespace eval [namespace current] ... ====== This brings the namespace variables into sight, but the local variables of the proc are not visible - kind of like an [uplevel] effect for scope: ====== namespace eval foo {variable grill 42} proc foo::bar {x} { namespace eval [namespace current] { concat $grill $x } } % foo::bar what can't read "x": no such variable ====== <> [kruzalex] Making local variables of the proc visible: ====== namespace eval foo {variable y 42} proc foo::bar {x} { upvar y z puts [concat $z $x] } namespace eval foo {bar what} ====== ---- ''[JCW] wrote in [the comp.lang.tcl newsgroup]:'' For variables, I've found a child namespace to be very convenient. Instead of: ====== namespace eval TO { variable foo proc proc1 {} { variable foo ... use $foo ... } } ====== Consider using: ====== namespace eval TO { namespace eval v { variable foo } proc proc1 {} { ... use $v::foo ... } } ====== No more lists of "variable" calls inside each proc. The other way is to put all your variables inside a single array, but my impression is that the v::* approach is slightly faster ("variable" seems to take a bit of time, don't know why). <> ---- ***Variable Resolution Weirdness*** [ulis], 2003-11-16. Try this: ====== set ::version 1.0 namespace eval ns { set version 0.9 } puts $::version catch { puts $ns::version } msg puts $msg ====== Result: 0.9 can't read "ns::version": no such variable Explanation: As stated in the Tcl manual: ''if the name does not start with a :: (i.e., is relative), Tcl follows a fixed rule for looking it up: Command and variable names are always resolved by looking first in the current namespace, and then in the global namespace. '' In the above script the variable ''version'' wasn't defined inside the namespace so Tcl used the existing global variable. To avoid that ''always'' define namespace variables with the '''variable''' command: ====== set ::version 1.0 namespace eval ns { variable version 0.9 } puts $::version catch { puts $ns::version } msg puts $msg ====== New result: 1.0 0.9 <> I ([ulis]) think that it would be better than the search in the global space was used when refering a variable and avoided when setting a variable. Furthermore, when referring a variable or a proc in a namespace embedded in other namespaces, Tcl first searches the current namespace and then the global namespace (as documented) and '''doesn't look in any intervening embedding namespaces''': ====== proc ::p {} { puts "I'm ::p" } namespace eval ns { proc p {} { puts "I'm ns::p" } namespace eval child { p } } ====== Result: I'm ::p Tcl resolved the name in the global namespace and didn't search in the intervening ''ns'' namespace. <> ---- **Copying namespaced commands to other namespaces** Currently, the typical idiom for importing commands as functions into tcl::mathfunc is creating an alias with "interp alias", which has the nasty effect of incurring some performance degradation on each invocation of the alias. If the respective command has been exported ("namespace export") from its own namespace, then it can also be imported ("namespace import") into another, and that not only makes execution of the thusly imported command considerably faster, it is even robust against later renaming (though not against later deletion) of the original. Sometimes one might wish for more than what "namespace import" currently provides: 1. one might want to access commands from a namespace where they are not exported from. e.g.: ::tcl::unsupported doesn't export anything, so disassemble cannot just be imported. 2. one might want to import commands to a different name. e.g.: one might want to import tcl::string::length to a local strlen 3. a special one: if one tries to import only the multiplication operator from ::tcl::mathop::* then the asterisk is interpreted as a pattern, and everything is going to get imported. I've written a procedure, that looks a bit complicated/awkward, but addresses all these shortcomings. Here it is: proc alias {src tgt} { set nsrc [namespace qualifiers $src]; set tsrc [namespace tail $src] set oe [uplevel 1 [list namespace eval $nsrc { namespace export }]] uplevel 1 [list namespace eval $nsrc { namespace export * }] set n 0; while {[namespace exists tmp-[incr n]]} {} set fqsrc [uplevel 1 [list namespace which -command $src]] namespace eval tmp-$n [list namespace import $fqsrc] uplevel 1 [list rename [namespace which -command "tmp-${n}::$tsrc"] $tgt] uplevel 1 [list namespace eval $nsrc [list namespace export -clear {*}$oe]] namespace delete tmp-$n } In Tcl8.6+ you could create this procedure named as ::tcl::namespace::alias instead, and add it to the ensemble with three more awkward lines: set nsmap [namespace ensemble configure namespace -map] set nsmap [dict merge $nsmap [dict create alias ::tcl::namespace::alias]] namespace ensemble configure namespace -map $nsmap In Tcl8.5 "namespace" isn't an ensemble yet, but the global proc "alias" works just fine with Tcl8.5. Examples: alias ::tcl::string::length ::tcl::mathfunc::strlen ;# import "string length" as "strlen" to be used within expr alias ::tcl::unsupported::disassemble disasm ;# save some typing in an interactive shell :) Note: unlike "interp alias" you can not append any extra arguments with this "alias". However, if the intended argument is really just the subcommand of an ensemble (as is string length), then you can simply alias the subcommand directly :-) Known bugs: specifying bad arguments may leave some empty namespace and export-patterns behind. That could be fixed with try-finally or catch, but I thought it was already complicated enough as it is without fancy error-handling. Also, it would be nice to be able to specify more src/tgt pairs on one invocation... <> none, yet. <> ---- **Open questions** <> [LV] 2007 June 11 - anyone have comments/suggestions/observations/warnings about the use of namespaces as the means to collect an application's data that is to be shared between procs and source files, as opposed to using global variables? ---- '''[JeremyM] 19 Sept 2007''' I'm struggling with the decision as to whether to use a namespace or an object to hold code and variables that are a singleton, i.e. if I use an object, I will always instantiate exactly one instance of the object. Because of this, a namespace seems like a more appropriate container, but I'm getting the feeling that namespaces are somewhat obsolete. PLus I'm not crazy about mixing the two syntaxes in one set of scripts. So the question is, what is the best way to hold a block of code and variables that are a singleton? [Bryan Oakley] 19 Sept 2007 - There is no definitive "best way". I use namespaces all the time. I even use them for "objects" that aren't singletons. I've done it so many times I can (almost, but I keep trying!) do it with my eyes closed. Namespaces are much more portable than objects since, as of this writing, they are part of the core and OO is not. If portability is not a concern and you already use an object system, it makes sense to continue to use an object system. ---- ***Private namespaces*** ''Anonymous'': There should be a facility in tcl to define a [private namespace]. And, in a completely different direction, [Darren New] points out that [tcllib] would be a good home for a namespace serializer, that is, a [proc] which writes out a namespace's content in a form that can be read back in to recreate the namespace exactly. [Stu] 2007-09-30 Creating a randomly named namespace with global vars cleanup. Left-to-right evaluation and the fact that [for] and [unset] return empty strings are what makes it possible. ====== # Random namespace (10 chars, A-Z) with vars cleanup namespace eval [ for {set ns {};set i 0} {$i < 10} {incr i} { append ns [format %c [expr {65 + int(rand() * 26)}]] } ][unset i][set ns][unset ns] { puts [namespace current] # Other stuff: variables, procs, etc. } ====== ([Lars H], 2007-10-02: Edited the above to make it more readable. Technically it's sufficient that [unset] returns an empty string, as the first three command substitutions in the namespace argument of [namespace eval] could be combined into one. Realistically, the [for] loop should be in a procedure instead to avoid using global variables at all...) [Stu] 2008-11-16 Lars, could you please date your comments? The one you added below in the middle of the paragraph arrived a year after the original discussion, when [apply] did not even exist. So yes, now with Tcl 8.5, it can be done with apply ... I guess ... you didn't provide an example. [Stu] 2007-10-02 But where would you put the command? The idea here is to pollute the global namespace as little as possible and to create a unique namespace so that we're not "stepping on anyone's toes." ''— [Lars H]: Well, use [apply] then. —'' If one writes namespace-agnostic code then one should be able to 'source' their code into unknown environments without problems. Even with a [proc] we still pollute the global namespace - one proc versus two variables seems like a step in the right direction. This is a bit better (I like it in one line but this is easier to read/understand): ====== # Random namespace (10 chars, A-Z) with cleanup, using [proc] with empty proc name. namespace eval [ proc {} {} { set ns {} for {set i 0} {$i < 10} {incr i} { append ns [format %c [expr {65 + int(rand() * 26)}]] } return $ns } ][{}][rename {} {}] { puts [namespace current] # Other stuff: variables, procs, etc. } ====== Using [eval], I can elminate all procs and vars and it's much smaller more readable: ====== # Random namespace (10 chars, A-Z) with cleanup. namespace eval [eval return [string repeat {[format %c [expr {65 + int(rand() * 26)}]]} 10]] { puts [namespace current] # Other stuff: variables, procs, etc. } ====== This gives an interesting result which I don't understand just yet. Put the above (with [eval]) code in a file: namespacetest.tcl ====== $ tclsh namespacetest.tcl ::HTUZNJTKOE $ tclsh % source namespacetest.tcl NIDZGBNLJP ====== Where is the :: ? [DKF]: Seems to me like the [return] might be confusing things, causing the evaluation to stop before the [namespace eval]'s body fires. In 8.5 use '''[return] -level 0''' instead. [Stu] 2007-10-02 Ok then, (and even better) without [eval]: ====== namespace eval [subst [string repeat {[format %c [expr {65 + int(rand() * 26)}]]} 10]] { puts [namespace current] # Other stuff: variables, procs, etc. } ====== [Stu] 2008-10-31 Ultimate random namespace, like ::TkTwig!(20081031023934)1500 ====== #! /bin/sh # \ exec tclsh "$0" ${1+"$@"} package require Tcl; namespace eval \ MyProg!([clock format [clock seconds] -format %Y%m%d%H%M%S])[pid]<[subst \ [string repeat {[format %c [expr {97 + int(rand() * 26)}]]} 10]]> { # program goes here }; #End of namespace # EOF ====== <> ---- **See Also** * [namespace size] * [Thoughts on Namespaces and OO] * [Namespace variables 2] * [Namespace resolution of Variables & Procedures] * [data is code] <> Command | Introspection | Tcl syntax help | Arts and Crafts of Tcl-Tk Programming