Tcl Part I · Module 11 · Scope and Namespaces
namespace eval: Giving Names a Home
Chapter 10.1 ended on an uncomfortable fact: there is one flat table of commands, and defining a procedure that already exists replaces it silently, with nothing recording that the first one was ever there. For a script you wrote entirely yourself that is survivable. For two libraries written by different people that happen to agree on the word check, it is not. Namespaces are Tcl's answer — a way to give a group of related procedures a shared surname, so that loading one library cannot quietly break another. This chapter is about procedures only; the variables that go with them are the next chapter's subject, because they have a trap of their own.
Intermediate11 min readTclPart INamespacesLibrariesScope
Part I · Module 11 · Chapter 11.6 · namespace eval: Giving Names a Home
1. The problem
From Chapter 10.1 §6, restated because it is what this chapter fixes:
# as if from one library
proc check {x} { return "library A checked $x" }
# as if from another, loaded afterwards
proc check {x} { return "library B checked $x" }
puts [check 1]
puts "definitions registered: [llength [info procs check]]"library B checked 1
definitions registered: 1One command, last writer wins, no warning. Two independent libraries cannot both have a check.
2. namespace eval
namespace eval report {
proc write {path} {
return "writing report to $path"
}
}
puts [report::write out.txt]writing report to out.txtnamespace eval name script creates the namespace if needed and runs the script inside it. A proc defined there gets the namespace as a prefix, and is called with :: between the parts.
The unqualified name does not exist outside:
write out.txtinvalid command name "write"Which is exactly the point — report::write cannot collide with anything that is not also called report::write.
3. The collision is gone
Two libraries, same procedure name, both intact:
namespace eval libA {
proc check {x} { return "A checked $x" }
}
namespace eval libB {
proc check {x} { return "B checked $x" }
}
puts [libA::check 1]
puts [libB::check 1]A checked 1
B checked 1Both exist, neither replaced the other, and the call site says which one it means.
4. Inside a namespace, the short name works
A procedure in a namespace can call its siblings without qualification:
namespace eval maths {
proc double {n} { return [expr {$n * 2}] }
proc quadruple {n} { return [double [double $n]] }
}
puts [maths::quadruple 5]20quadruple called double by its short name because they share a namespace. From outside, both need the prefix.
This also means a namespace procedure can shadow a global command of the same name — for calls made inside that namespace only:
proc describe {} { return "the global one" }
namespace eval shadowy {
proc describe {} { return "the namespace one" }
proc call {} { return [describe] }
}
puts "inside : [shadowy::call]"
puts "outside : [describe]"inside : the namespace one
outside : the global oneTwo commands named describe, each reached from its own context, neither disturbing the other.
5. Namespaces nest
namespace eval outer {
namespace eval inner {
proc deep {} { return "reached the inner one" }
}
}
puts [outer::inner::deep]reached the inner oneA nested namespace is reached by joining the parts. From inside outer, the relative name works:
namespace eval outer {
proc call_relative {} { return [inner::deep] }
}
puts [outer::call_relative]reached the inner oneFrom the global scope it does not — inner::deep means a top-level namespace called inner, which does not exist:
inner::deepinvalid command name "inner::deep"6. Adding to an existing namespace
namespace eval on a name that already exists adds to it rather than replacing it:
namespace eval tools {
proc first {} { return "first" }
}
namespace eval tools {
proc second {} { return "second" }
}
puts [tools::first]
puts [tools::second]
puts "commands: [lsort [info commands ::tools::*]]"first
second
commands: ::tools::first ::tools::secondThat is what lets a library be split across several files, each contributing to the same namespace.
7. Finding out what is there
namespace eval probe {
proc alpha {} {}
proc beta {} {}
}
puts "commands : [lsort [info commands ::probe::*]]"
puts "is probe a child of ::? [expr {[lsearch [namespace children ::] ::probe] >= 0}]"
namespace eval probe {
puts "current inside : [namespace current]"
}
puts "current at top : [namespace current]"commands : ::probe::alpha ::probe::beta
is probe a child of ::? 1
current inside : ::probe
current at top : ::namespace current answers "where am I?", which is the first thing to check when a qualified name is not resolving the way you expect.
8. A worked example
A small reporting library, defined in one namespace and used from outside:
namespace eval report {
proc header {title width} {
return "[string repeat = $width]\n$title\n[string repeat - $width]"
}
proc row {name value} {
return [format " %-12s %s" $name $value]
}
proc render {title rows} {
set out [header $title 32]
foreach {name value} $rows {
append out "\n" [row $name $value]
}
return $out
}
}
puts [report::render "Run summary" {cycles 12000 errors 0 warnings 4}]================================
Run summary
--------------------------------
cycles 12000
errors 0
warnings 4render called header and row by their short names because they are siblings. A caller outside uses report::render, and nothing in this library can collide with a render or a row defined anywhere else.
9. Exercises
Exercise 1. What problem do namespaces solve, and what did Chapter 10.1 call it?
Exercise 2. Define a namespace geometry with a procedure area taking a width and height, and call it from outside.
Exercise 3. Why does calling write unqualified fail after namespace eval report { proc write ... }?
Exercise 4. Can two namespaces both define a procedure called check? What does each call site look like?
Exercise 5. What does a second namespace eval tools { ... } do to the procedures defined by the first?
Exercise 6. A procedure inside a namespace calls puts. Why does that work without qualification?
Answers
1. Silent collision in the single flat command table: defining a procedure whose name already exists replaces it with no warning, so two libraries cannot both define check. Chapter 10.1 §6 called it silent redefinition.
2.
namespace eval geometry {
proc area {w h} { return [expr {$w * $h}] }
}
puts [geometry::area 3 4]123. Because the procedure's name is report::write, not write. The short name exists only for calls made from inside the same namespace; from the global scope there is no command called write, so Tcl reports invalid command name "write".
4. Yes. Each is a distinct command — libA::check and libB::check — and each call site names the one it means. Neither definition affects the other.
5. Nothing — it adds to the namespace rather than replacing it. Both procedures end up defined, which is how a library can be split across several files.
6. Because command lookup falls back to the global namespace when a name is not found in the current one. puts is not defined in the namespace, so Tcl finds the global one. (Variable lookup does not fall back this way, which Chapter 11.8 covers.)
10. Remember
- Namespaces solve silent collision in Tcl's one flat command table.
namespace eval name {script}creates the namespace if needed and runs the script inside it.- A procedure defined there is called as
name::procfrom outside; the unqualified name does not exist there. - Two namespaces can define the same short name without interfering.
- Inside a namespace, siblings are callable by their short names, and a namespace procedure can shadow a global command for calls made within that namespace.
- Global commands remain available unqualified, because command lookup falls back to the global namespace.
- Namespaces nest, and a relative name works only from inside the parent.
- A second
namespace evalon the same name adds to it, which lets one library span several files. namespace currentandinfo commands ::ns::*tell you where you are and what is defined.
Where this fits
Part of the Tcl curriculum.
