Like `[uplevel] 1` except that it also causes the current scope to terminate, though the command is looked up in the current context first. Consequence of [NRE]. : '''tailcall''' ''command'' ?''arg''...? proc fred {} { george } proc george {} { proc george {} { tailcall harry } If I call fred, it's almost as though fred called harry directly, instead of george. Not so? [MS]: yup - all traces of george are gone from the program stack when harry is [MS] yup - all traces of george are gone from the program stack when harry is called. Now, if harry resolves to a different command in george's current namespace than it would under fred's, the harry that is called is george's and not fred's (no diff if the commands are FQ, of course). I think this does pretty much what delegation is supposed to do, right? ---- [jima] (2009-10-15) Perhaps this has been asked before or somewhere else... [jima] 2009-10-15: Perhaps this has been asked before or somewhere else... I mean, once fred knows that has to call harry directly the bytecodes generated I mean, once fred knows that has to call harry directly the bytecodes generated would be the ones equivalent to have said: proc fred {} { harry } I reckon I am not familiar with all the internals of Tcl but I find this would be an interesting thing. Wouldn't this be a new way to have some sort of macros? [MS]: Currently, `tailcall` is not bytecompiled. Everything happens at [MS] As of today [tailcall] is not byte compiled, everything happens at runtime. That extremely simple example could indeed be bytecoded in a minute, but things get more involved as soon as [[fred]] has a bit more structure to it: arguments, local variables, namespace issues both for variable and command lookup, multiple exit points with different (or no) [tailcall] in them, etc. [jima]: Thanks a lot Miguel for the answer. I see the point. I guess this is [jima]: Thanks a lot Miguel for the answer. I see the point. I guess this is the same with uplevel 1, isn't it? proc fred {} { uplevel 1 { #code here } } Would it be interesting to define a case (like a contract) saying if your proc is simple enough then it gets bytecompiled and you get some benefits? [MS]: you do not mean "bytecompiled" but rather "inlined into the caller", as [MS] you do not mean "bytecompiled" but rather "inlined into the caller", as all proc bodies get bytecompiled. There are quite a few other issues with that, especially to accomodate Tcl's dynamic nature. Changing one inlined proc would cause a spoiling of all bytecodes and recompilation of the world, at least with the current approach to bytecode lifetime management. [AMG]: Sounds a lot like '''exec''' in [Unix shells]. [AMG]: Sounds a lot like `exec` in [Unix shells]. See [execline] for more ---- See also [TIP]#[http://tip.tcl.tk/327%|%327] ---- ***Interaction with [try]*** === '''%''' proc foo {} {puts "I'm foo"} '''%''' proc bar {} {puts "I'm bar"; try { tailcall foo } finally { puts "exitting" }} ''I'm foo'' '''%''' bar ''I'm bar'' ''exiting'' ''exitting'' === 31-03-2015 [HE] I'm sure ;-) that I don't understood what happend there. Why "exiting" is printed before "I'm foo" when I call bar? [wdb]: Apparently, the `tailcall` closes one of the last gaps in [wdb] Appearantly, the command ''tailcall'' closes one of the last gaps in Tcl: Tail recursion as known in [Scheme] ---- **Emulation** [Lars H], 2010-05-09: As of late, when writing an [uplevel], I've sometimes found myself thinking "That would be slicker with [tailcall], but I can't rely on 8.6 features in this project". Today it occurred to me that one can however use a [proc] to emulate the properties of [tailcall] that would be needed in these cases, and thus provide a route for forward compatibility. The main situation I've encountered is that of delegating to another command which may make use of [upvar] or [uplevel]. That's basically taken care of by proc utailcall {args} {uplevel 2 $args} proc utailcall {args} {return -code return [uplevel 2 $args]} in case the "terminate proc early" aspect of [tailcall] is relied upon; this is easy to do without thinking much about it. Another aspect of `tailcall` is the name resolution of the called command. Another aspect of [tailcall] is the name resolution of the called command. This can be done as follows proc ntailcall {cmd args} { [uplevel 1 [list ::namespace which $cmd]] {*}$args [uplevel 1 [list ::namespace which $cmd]] {*}$args } } proc untailcall {cmd args} { uplevel 2 [list [uplevel 1 [list ::namespace which $cmd]]] $args uplevel 2 [list [uplevel 1 [list ::namespace which $cmd]]] $args } } A word of warning here is that this will produce a very confusing error message if the command is undefined, as [namespace which] returns an empty string in that case. A third aspect is that of preserving `[return]` levels. A third aspect is that of preserving [return] levels. proc rtailcall {args} { dict incr options -level 2 return -options $options $result } } This leaves some extra material in the [errorInfo], but one can probably live with that. Combining the "r" and "u" aspects is straightforward, but will leave even more: proc rutailcall {args} { catch {uplevel 2 $args} result options dict incr options -level 2 return -options $options $result } To complete the set, one might just as well write down the combination of the "r" and "n" aspects proc rntailcall {args} { catch { [uplevel 1 [list ::namespace which $cmd]] {*}$args } result options dict incr options -level 2 return -options $options $result } proc rnutailcall {args} { catch { uplevel 2 [list [uplevel 1 [list ::namespace which $cmd]]] $args } result options dict incr options -level 2 return -options $options $result } But note: all of the above will fail if used for tail recursion, as soon as the loops get long enough. <> Command | Control structure