user707549
user707549

Reputation:

how to define a proc in tcl namespace

I saw some code in TCL like this:

namespace eval ::info {
    set count 0;
    set id 1;
    set role admin;

    namespace export *
}



proc ::info::setcount {
    set ::info::count 0;
}

proc ::info::setId {
    set ::info::id 1;
}

proc ::info::setRole {
    set ::info::role user;
}

There are three variables defined in namespace ::info, but that three procs(setcount setId setRole) are not declared in the namespace, seems like they are defined outside of ::info, is this allowed? how does this work?

Upvotes: 3

Views: 6114

Answers (2)

RHSeeger
RHSeeger

Reputation: 16262

The namespace eval command

  1. Creates the namespace if it doesn't exist
  2. Runs the code supplied to it from within that namespace

Procs defined from within a namespace (which is all procs, since the default namespace is ::)

  • If preceded by an absolute namespace, will define that command in the specified namespace
  • If preceded by a relative namespace, will define that command relative to the current namespace

As such

namespace eval bob {
    namespace eval joe {
        proc proc1 {} {}
    }
    proc proc2 {} {}
    proc ::proc3 {} {}
    proc joe::proc4 {} {}
}
proc proc5 {} {}
proc bob::joe::proc6 {} {}
proc ::bob::joe::proc7 {} {}

The following commands will exist

::bob::joe::proc1
::bob::proc2
::proc3
::bob::joe::proc4
::proc5
::bob::joe::proc6
::bob::joe::proc7

Notice that commands in the global namespace, when called from the global namespace, can be preceeded by a :: or not. The same is true of commands in any namespace.

namespace eval bob {
    proc2 ;# calls ::bob::proc2
    ::proc5 ;# calls ::proc5 (proc5 in the global namespace)
    joe::proc4 ;# calls ::bob::joe::proc4
}

It is worth noting that a raw command name (with no namespace qualifiers at all) will look in the current namespace and then, if it doesn't find the command there, the global namespace.

namespace eval bob {
    proc5 ;# calls ::proc5 since there is no ::bob::proc5
}

Upvotes: 4

Donal Fellows
Donal Fellows

Reputation: 137567

The procedures are defined in the ::info namespace. They're just not inside the scope of the namespace eval, a command that just creates the namespace if necessary and then executes the given script within that context. Being executed within the context of a namespace changes how proc places commands that it creates when the names of those commands are not fully-qualified. The namespace exists independently of the namespace eval call. The variables have to be declared in the namespace though; that avoids some really nasty trouble with resolution of variables that can catch people out.

Personally, I prefer to write code like this:

namespace eval ::foo {
    proc bar ... {
        ...
    }
}

But I know that other people disagree with me. Write what you prefer, as Tcl works just fine with either scheme.

Upvotes: 5

Related Questions