Arne
Arne

Reputation: 1151

Load package into current namespace

How can I load the contents of a package into the current namespace instead of the global namespace?

Suppose I have the following package.tcl

package provide pgkTest 1.0

variable _value ""
proc get_value {} {
  variable _value
  return _value
} 

The package is listed in pkgIndex.tcl and is found. Now in the main script in another folder I would like to do:

namespace eval myns1 {
   package require pgkTest 1.0
   package forget pgkTest 
}

namespace eval myns2 {
   package require pgkTest 1.0
   package forget pgkTest 
}

However, this does not seem to work because the package is loaded into the global namespace :: by default.

Upvotes: 1

Views: 262

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137557

What you're trying to do won't work, because each package (as determined by its name) is loaded at most once into an interpreter. Instead, the package probably ought to provide a command that sets up a given namespace with the features you're after:

package provide pgkTest 1.0

namespace eval ::pgkTest {}
proc ::pgkTest::setup {{targetNamespace ""}} {
    # If caller doesn't give a namespace, get the caller's namespace
    if {$targetNamespace eq ""} {
        set targetNamespace [uplevel 1 {namespace current}]
    }
    namespace eval $targetNamespace {
        variable _value ""
        proc get_value {} {
          variable _value
          return _value
        } 
    }
}

Then you can do this to get the effect you want:

package require pgkTest 1.0

namespace eval myns1 {
    ::pgkTest::setup
}

namespace eval myns2 {
   ::pgkTest::setup
}

If you're really doing this sort of thing a lot, consider switching to using an object system like TclOO, [incr Tcl], or XOTcl. They're designed much more for tackling the problem of stamping out lots of copies of things that are all the same (or have minor variations).

Upvotes: 1

Related Questions