Reputation: 1193
I want to write a function that can be used like this:
my_function {
cmdA argA_1 argA_2
cmdB argB_1 argB_2
cmdC argC_1 argC_2
}
I want to implement my_function by using namespace eval ::my_internal_namespace [uplevel ...]
, possibly in a loop. Although this is not immediately very useful, I will enhance it later to do more than merely uplevel
.
my_internal_namespace
would be defined something like this:
namespace eval my_internal_namespace {
proc cmdA { args } {
puts "$args"
}
proc cmdB { args } {
puts "$args"
}
proc cmdC { args } {
puts "$args"
}
}
I think this technique will ultimately allow the caller of my_function to declare some facts and behaviours that they would like from my_function, where the parameters of those facts and behaviours are evaluated in the context of the caller, for example, to get the value of variables or to perform other substitutions in the namespace and scope of the caller.
Upvotes: 0
Views: 120
Reputation: 137557
Why not just pass the word to namespace eval
directly? That's almost what Tcl does itself in situations like the oo::define
command. Evaluate as a script is a wonderfully easy way to parse some trusted code.
namespace eval ::my_internal_namespace $the_user_word
For untrusted code, a safe interpreter is recommended. For these “little language” approaches, you're best to create a basic safe interpreter, hide the remaining commands that you don't want to expose, and add in aliases for all the commands that you want to make available.
set i [interp create -safe]
foreach cmd [$i eval {info commands}] {
$i hide $cmd
}
foreach cmd {cmdA cmdB cmdC} {
$i alias $cmd ::my_internal_namespace::$cmd
}
$i eval $the_user_word
This is fairly expensive to just doing a namespace eval
; I wouldn't bother if the code is relatively trusted.
Upvotes: 1