Reputation: 1151
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
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