I'm experimenting a little with TclOO from Tcl8.6 and Rivet, but I'm in trouble, because I'm not able to do what I want.
The problem is simply reproduceable with the following code inside a .rvt
file:
<?
proc dumbproc {} {
puts "this is dumbproc ([namespace current])"
}
oo::class create foo {
method bar {} {
puts "this is bar ([namespace current])"
dumbproc
}
}
set obj [foo new]
dumbproc
$obj bar
If I simply look at the code, it seems it should work as expected, but it really doesn't because a subtle behavior of the Rivet package and the specific configuration choosen.
In this example, I'm using a .rvt
file whose code is executed inside the ::request
namespace, so the fully qualified name of the dumbproc
procedure is ::request::dumbproc
. When the name resolution algorithm is called inside the bar
method, it searches for dumbproc
inside ::oo::Obj12
, then in ::oo
, and finally in ::
, without finding it and giving the following error.
this is dumbproc (::request) this is bar (::oo::Obj16)
invalid command name "dumbproc"
while executing
"dumbproc"
(class "::request::foo" method "bar" line 3)
invoked from within
"$obj bar"
(in namespace eval "::request" script line 21)
invoked from within
"namespace eval request {
puts -nonewline ""
proc dumbproc {} {
puts "this is dumbproc ([namespace current])"
}
oo::class create..."
So, Tcl is right in doing what it does, a feature, then. But the behavior is unpredictable because when you write some class code, you must know the context it will be used in.
Indeed, I get the same error if I drop the starting <?
Rivet magic, put the code inside a test.tcl
file and use it in an interactive session:
$ tclsh
% namespace eval ::myns {source test.tcl}
this is dumbproc (::myns)
this is bar (::oo::Obj12)
invalid command name "dumbproc"
I tried to solve the issue by prepending the current namespace to the class creation code
::oo::class create [namespace current]::foo { ... }
then, I also tried to create the obj
object inside the namespace
::oo::class create [namespace current]::foo { ... }
namespace eval [namespace current] {set obj [[namespace current]::foo new]}
then, I switched to the create
method of the class for giving the object a qualified name which includes the namespace
foo create [namespace current]::obj
obj bar
but everything was unsuccessful. Every trial shows that, no matter how I do it, a method inside a TclOO class is always executed inside its object unique namespace. Am I wrong?
Is there a way to get what I want? Is TclOO not intended to work that way, and in this case why? What really surprise me is this context-dependend behavior, which I'm not sure it's the right thing, but maybe I'm completely wrong and there are sound cases for it, which I'm missing.