Skip to content
VLSI Mentor

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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# 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]]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
library B checked 1
definitions registered: 1

One command, last writer wins, no warning. Two independent libraries cannot both have a check.

2. namespace eval

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
namespace eval report {
    proc write {path} {
        return "writing report to $path"
    }
}

puts [report::write out.txt]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
writing report to out.txt

namespace 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
write out.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
invalid 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
A checked 1
B checked 1

Both 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
namespace eval maths {
    proc double {n} { return [expr {$n * 2}] }
    proc quadruple {n} { return [double [double $n]] }
}

puts [maths::quadruple 5]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
20

quadruple 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
inside  : the namespace one
outside : the global one

Two commands named describe, each reached from its own context, neither disturbing the other.

5. Namespaces nest

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
namespace eval outer {
    namespace eval inner {
        proc deep {} { return "reached the inner one" }
    }
}

puts [outer::inner::deep]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
reached the inner one

A nested namespace is reached by joining the parts. From inside outer, the relative name works:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
namespace eval outer {
    proc call_relative {} { return [inner::deep] }
}
puts [outer::call_relative]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
reached the inner one

From the global scope it does not — inner::deep means a top-level namespace called inner, which does not exist:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
inner::deep
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
invalid 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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::*]]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
first
second
commands: ::tools::first ::tools::second

That is what lets a library be split across several files, each contributing to the same namespace.

7. Finding out what is there

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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}]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
================================
Run summary
--------------------------------
  cycles       12000
  errors       0
  warnings     4

render 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.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
namespace eval geometry {
    proc area {w h} { return [expr {$w * $h}] }
}
puts [geometry::area 3 4]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
12

3. 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::proc from 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 eval on the same name adds to it, which lets one library span several files.
  • namespace current and info commands ::ns::* tell you where you are and what is defined.

Where this fits

Part of the Tcl curriculum.