Thursday, 26 May 2011
Coping without Namespaces
One of the features of Tcl which Jim lacks is support for namespaces.
The lack of namespaces in Jim is generally not a problem in the small, embedded applications for which Jim is most suited. However occasionally it useful to be able to port Tcl code which uses namespace. For example, tcllib makes heavy use of namespaces. This article describes one approach to easily porting this code to Jim.
For this example, we will port dns.tcl to Jim.
The general approach is to modify the code from using implicit scoping to using explicit scoping. Consider the following code which uses namespaces to declare a proc and a variable within a namespace.
namespace eval dns { variable timeout 10 proc configure {new} { variable timeout set timeout $new } }
This code create a variable ::dns::timeout
and a proc ::dns::configure
. We can do the same
explicitly.
set dns::timeout 10 proc dns::configure {new} { global dns::timeout set dns::timeout $new }
The main differences between this code and the namespace code are:
- All variables and procs are visible, even if not exported
- Namespace procs need to be referenced with a fully qualified name
- Namespace variables need to be referenced with a fully qualified name
We can mitigate this last difference with one small change.
# Poor man's variable for Jim Tcl # Links a global variable, ::ns::var to a local variable, var proc variable {ns var} { uplevel 1 [list upvar #0 ${ns}::$var $var] } set dns::timeout 10 proc dns::configure {new} { variable dns timeout set timeout $new }
With this change, code can refer to the unqualified variable name which is linked to the fully qualified name.
You can see the fully converted version of dns.tcl for Jim
To summarise:
- Remove
namespace eval
- Initialise variables with fully qualified names:
set ns::var value
- Ensure procs are declared with fully quality names:
proc ns::procname { ... }
- Use fully qualified names when invoking procs within the namespace.
- Replace the use of
namespace current
with the namespace name - Replace the use of
namespace origin
with the namespace name - Use the
variable
proc to declare variables within procs
Steve Bennett (steveb@workware.net.au)
comments powered by Disqus