Creating a proc on the fly can lead you directly into quoting hell. Here's a simple command to create a new proc that avoids quoting hell quite nicely.
proc mkproc {name arglist body args} {
set body [string map $args $body]
proc $name $arglist $body
}
For example, suppose you're creating a object command; it will call an instance command, passing in its own name, the subcommand, and any arguments. Supposing that $instance is "myObj", this command:
mkproc $instance {method args} {
::MyPackage::InstanceCmd %SELF% $method $args
} %SELF% $instance
will define this proc:
proc myObj {method args} {
::MyPackage::InstanceCmd myObj $method $args
}
Even in this simple case, this is clearer than the alternatives. The following method works at the cost of some nasty backslashes, and it gets worse if you need any quotation marks in the body of the proc.
proc $instance {method args} \
"::MyPackage::InstanceCmd $instance \$method \$args"
Or you can do this, but the use of the format command obscures the real code:
proc $instance {method args} \
[format {::MyPackage::InstanceCmd %s $method $args} $instance]
--
WHDLars H, 2007-11-08: It is probably more common to use
interp alias to define such instance commands, like so:
interp alias {} $instance {} ::MyPackage::InstanceCmd $instance
This has the advantage over the proc definition (for which Yet Another Definition is:
proc $instance {method args} "[list ::MyPackage::InstanceCmd $instance] \$method \$args"
) that you can [uplevel 1] or [upvar 1] out of the ::MyPackage::InstanceCmd, as one would usually expect to do.