In Tcl, nothing is especially sacred. You can use anything in the language with pretty much anything else. In particular, you can use any string-generating command (all of them actually, though some only produce the empty string) to produce a body of a procedure; proc
is just an ordinary Tcl command (that happens to make other Tcl commands, though there are others that do that too).
In your specific case, you might be better off using a different approach though.
set original_proc_name foo
interp alias {} helper_$original_proc_name {} apply {{cmd val} {
$cmd $val
}} $original_proc_name
OK, this looks more than a bit magical. It's not really. Let's work from the inside out.
apply
is a command that effectively works like a nameless procedure. It's first argument is a list (usually with two elements) that defines the arguments to the “procedure-like” thing and the body. It's subsequent arguments are the actual arguments. Thus,
apply {{a b} {
puts "a=$a and b=$b"
}} 123 456
will print a=123 and b=456
. We're using that with a specific body that takes two arguments and applies one to the other; the first argument is a command name (presumably) and the second is the value to send to that command. So we go:
apply {{cmd val} {
$cmd $val
}} puts "Hi"
and we get a very mundane piece of code indeed. Where's the benefit?
Well, we're using interp alias
here. This particular form:
interp alias {} foo {} bar boo
makes it so that when you use foo
as a command, Tcl hands off the invokation to bar boo
, appending on any extra arguments to foo
. In a simple case:
interp alias {} writeError {} puts stderr
gives us a command that will write messages to stderr like this:
writeError "GRUMPY CAT WANTS NO PART OF THIS!"
OK, so we're putting these two things together.
interp alias {} helper_$original_proc_name {} apply {{cmd val} {
$cmd $val
}} $original_proc_name
Here, the command alias we're making is generated by string substitution, and we're doing a partial application of the inner simple invoker so that it is locked to the original command name. The result is that we've made helper_foo
be a command that only ever takes one argument, and that passes that argument on to the original foo
for handling.
And all without complicated string substitution.
This case is perhaps a little overkill, but for more complicated tasks it's much simpler than generating correct scripts. It's also slightly more overkill than this, which I'd use in my own code:
interp alias {} helper_$original_proc_name {} $original_proc_name
But that's got subtly different semantics.
In Tcl 8.6 you've also got tailcall
. That can make things even more “interesting”. With great power comes great opportunity for irresponsibility…