1
votes

I have several functions defined in namespace "b" which I export. I then import these functions to namespace ::x::Y, thusly:

namespace eval ::x::y "namespace import fun"

some time later I do:

namespace eval ::x::y fun

Where fun does:

proc fun {} {
   puts "[namespace current]"
   uplevel {puts "[namespace current]"}
}

What is printed is:

::b
::x::y

What I want and need is for 'fun' to happen in ::x::y and not in ::b. What am I doing wrong?

1
Importing a procedure name from one namespace to another does not change the namespace where the procedure was defined and, consequently, does not change the current namespace when the procedure is invoked. Perhaps you could share more of your problem and some other ideas would arise. - andy mango
If you're trying to do a poor-man's OO, stop! Use one of the real OO systems (or 8.6.0, which has one baked in) that get this right. - Donal Fellows

1 Answers

1
votes

That's not how Tcl's namespaces work. Each procedure is associated with exactly one namespace, which is the one in which its name is located. When you use namespace import, an alias to the procedure is placed in the importing namespace that allows the procedure to be invoked from that other namespace, but the procedure itself remains in its original namespace and executes in that one.

If you want to know the caller's namespace, use uplevel namespace current (or uplevel 1 {namespace current} for a slightly windier but more efficient version). This doesn't actually tell you what namespace contained the command that was used to invoke the procedure though; for that, you need this monstrosity (in the invoked command):

namespace qualifiers [uplevel 1 [list namespace which [lindex [info level 0] 0]]]

Of course, if you're needing that a lot then you're probably doing something wrong. (That's obvious, given the length and complexity of code required to get the information.)

In particular, if you're pretending to do object orientation with this, please stop and use a real object system that gets all the tricky details right. Tcl 8.6.0 includes one (two, if you've got the contributed extensions), and there are many for older versions available as extension packages.