namespace eval evaluates a script in a given namespace.
args are concatenated together in the same fashion as eval, with with a space between each one, and the result is evaluated in the namespace called namespace. namespace and any namespaces that qualify it are automatically created as necessary.
Unlike eval, namespace eval operates at a new level, such that uplevel 1 accesses the level from which namespace eval was called. In spite of this, return within namespace eval script operates as if it were uplevel return, i.e., it causes the caller of namespace eval to return. It would probably be more useful if return within a namespace eval script behaved the way it does within source ... script, causing only namespace eval itself to return.
For better performance, namespace eval ... is usually byte-compiled when it is given one argument which is a literal string:
proc main { namespace eval [info cmdcount] { set msg {this script is eligible to be byte-compiled} return $msg } }
PYK {2016 03 12} {2020 08 29}: namespace eval adds an evaluation level but doesn't allow a tailcall to replace that level. To create a command prefix that changes to some namespace to call the command, while arranging for the caller of the command to be one level up:
list apply [list args {::tailcall {*}$args} some_namespace] some command
The resulting command prefix is useful, for example, as the value of the -unknown option for a namespace ensemble. ycl ns call is an implementation of this.
A similar utility command is nseval. It's a little tedious to write the following common idiom:
namespace eval $namespace [list $some command with $some $arguments]
Instead we can write
nseval $namespace $some command with $some $arguments
nseval has a simple implementation
proc nseval {namespace args} { tailcall namespace eval $namespace $args }
ycl ns eval implements this.