Updated 2007-11-08 23:01:00 by dkf

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]

-- WHD

Lars 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.