Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

tailcall vs uplevel

43 views
Skip to first unread message

heinrichmartin

unread,
May 29, 2018, 4:23:16 AM5/29/18
to
Hi,
the example of [uplevel] at https://tcl.tk/man/tcl8.6/TclCmd/uplevel.htm#M5 caught my eye today: I wondered whether tailcall is a better choice (since it exists).

proc do {body while cond} {tailcall while 1 "$body\nif {!($cond)} break"} ;# simplified

seems to behave correctly, but I had two observations:

1. the uplevel version is way faster. I am quite sure this is related to byte-code for uplevel, but not for the body in the tailcall. And I don't see a possibility to hint the byte-code compiler, do you?

2. the error stack for wrong conditions contains all calls, i.e. do > while > if respectively do2 > uplevel > expr. Isn't this contradicting the documentation:

tailcall: "Apart from [command name] resolution, it is equivalent to return [uplevel 1 [list command ?arg ...?]]"
uplevel: "The uplevel command causes the invoking procedure to disappear from the procedure calling stack while the command is being executed."

Both answers will just deepen my understanding of internals - no crucial issues here :-)

Regards
Martin

Code reference:
expect1.1> proc do {body while cond} {tailcall while 1 "$body\nif {!($cond)} break"}
expect1.2> do {puts [incr i]} while {$i < 10}
expect1.4> do {puts [incr i]} while {$i < a}
11
invalid bareword "a"
in expression "!($i < a)";
should be "$a" or "{a}" or "a(...)" or ...
(parsing expression "!($i < a)")
invoked from within
"if {!($i < a)} break"
("while" body line 2)
invoked from within
"while 1 {puts [incr i]
if {!($i < a)} break}"
invoked from within
"do {puts [incr i]} while {$i < a}"
expect1.12> proc do2 {body while cond} {set condCmd [list expr $cond]; while {1} {uplevel 1 $body; if {![uplevel 1 $condCmd]} break}}
expect1.13> catch {unset i}; time {do {incr i} while {$i < 10}} 10000
9.9237 microseconds per iteration
expect1.14> catch {unset i}; time {do2 {incr i} while {$i < 10}} 10000
2.1511 microseconds per iteration
expect1.16> do2 {puts [incr i]} while {$i < a}
10010
invalid bareword "a"
in expression "$i < a";
should be "$a" or "{a}" or "a(...)" or ...
(parsing expression "$i < a")
invoked from within
"expr {$i < a}"
("uplevel" body line 1)
invoked from within
"uplevel 1 $condCmd"
(procedure "do2" line 1)
invoked from within
"do2 {puts [incr i]} while {$i < a}"
0 new messages