Updated 2013-01-20 09:15:44 by pooryorick

George Peter Staplin Dec 28, 2005 - I've been working on a project that needed to avoid infesting the global namespace with unprefixed names, so an obvious solution was to use namespace. However I can't do that as easily with ProcMeUp, so I came up with an alternative solution that is also in my opinion superior, and simpler than using namespace (for some uses). Why do I consider this superior? It allows creating a namespace that is named whatever the user desires, rather than what the package designer chose.

The concept is simple. You prefix each proc with NS_ and each global with NS_. NS_ is unlikely to occur in any other normal sequence, however of course it could be called something else.
proc NS_foo {a b c} {
    global NS_var
    set NS_var [list $a $b $c]

How does this allow the user to dynamically decide the namespace?

Let us imagine that the code above is in foo.tcl then we could do this (if foo.tcl is in the same directory as the current script):
 set fd [open [file join [file dirname [info script]] foo.tcl] r]
 eval [string map {"NS_" "super_"} [read $fd]]
 close $fd

That could all be factored into a proc such as source.namespace. For example:
proc source.namespace {f ns} {
    set fd [open $f r]
    # We use uplevel 1 to eval in the parent's scope.
    uplevel 1 [string map [list "NS_" $ns] [read $fd]]
    close $fd

source.namespace [file join [file dirname [info script]] foo.tcl] super_

So by now thanks to the string map we have:
proc super_foo {a b c} {
    global super_var
    set super_var [list $a $b $c]

This is also an easier way to update old packages, or code not designed for namespaces. Thus making it possible to bring that code into an environment where previous global variables or proc names would be problematic.

SLB Interesting. I had been thinking about new ways to use namespaces and have written up some thoughts in Local Packages and Transparent Namespaces.