1) Implementing a standard control structure.
This simply doesn't fit with the Tcl way of doing things. Remember, [if], [for] and [while] are all ordinary commands with no special privileges. If you want, you can even create your own control structures which are just as much a part of the language as they are. proc repeat {script untilKeyword expression} {
if {![string equal $untilKeyword "until"]} {
return -code error "malformed repeat: should be \"repeat\
script until expression\""
}
uplevel 1 $script
set test [list expr $expression]
while {![uplevel 1 $test]} {
uplevel 1 $script
}
}2) Resource cleanup on error exit.
Most Tcl resources are cleaned up automatically on exit from scope. The rest can be handled with the use of [catch] or something built on top of it; it is a better way to do it too, as it is writing code that is saying what you actually mean. (Alas, the code for try/finally is a bit too long for me to reproduce here.)KBK (8 November 2000) -- Here's one possible implementation of try ... finally ...KPV another C idiom for doing this to use 'do { ... } while(0);'. Inside that loop you have breaks, which essentially are goto's to the end of the loop.Lars H: Examples of how that idiom can be coded in Tcl: foreach dummy 1 {
# Code to jump out of goes here.
}
for {} 1 break {
# Code to jump out of goes here.
}
while 1 {
# Code to jump out of goes here.
break ; # Important! Needed to terminate loop.
}3) Creating a state-machine.
It is equally possible to use a mechanism based on Tcl arrays and [eval] to do this, like this: array set transition {
initialState state1
state1 {
set state state2
set x 1
}
state2 {
set state state3
incr x $x
}
state3 {
set state [expr {($x < 10) ? "state2" : "state4"}]
}
state4 {
break
}
}
set state $transition(initialState)
while {1} {eval $transition($state)}
puts $x ;# Can you guess what this does without running the code?This can even be extended fairly easily into working over events. I leave that as an exercise though.4) Err. I can't think of a 4) at the moment. :^)As you can see, you can do a lot with Tcl even without a goto. It often even ends up clearer to the person maintaining the code like that. Everyone's a winner!David Cuthbert comments on 4):If you're a code generator, you'll often use a goto for a combination of the above reasons. Of course, if you're a code generator, you're not human, and your code is not intended to be read by humans.You're also probably spitting out C or assembly instead of Tcl. :-)
KPV more comments on 4)In C, I've had to use a goto to break out of multiple loops. Newer languages have labeled loops and you can break to a label. For example:
for (i = 0; i < 100; ++i) {
for (j = 0; j < 100; ++j) {
if (IsFound(i,j)) goto found;
}
}
:foundulis,2002-09-03: You can easily have break labels in Tcl. See: http://wiki.tcl.tk/3402.SS Also note that you don't need break to exit from switch branches (like in C), so one of the uses of goto in C (to exit a while loop that contains switch) is a non-issue in Tcl:
while(1) {
x = get_next_x_value();
switch(x) {
case 1: ....; break
case 2: ....; break
case 3; goto out;
}
}
out:
something();In Tcl a break inside the switch will exit the while loop in similar code. Also note that in C is natural to have goto, because C maps quite directly to machine language, that's not the case of a scripting language like Tcl, this is why I use goto in C quite often, and I'm sure the way I use it makes the code more clear instead of spaghetti, but at the same time I don't want goto in Tcl because I feel it useless and probably dangerous for the code quality.History corner: on 1993-05-21, JO posted in c.l.t. [1] : "Actually I don't have a strong philosophical objection to goto. I think that goto's should be used very sparingly, but there are definitely situations where programs are a lot clumsier without them. The reason they're not in Tcl is that I haven't been able to figure out how to implement them (the structure of Tcl and its interpreter make it hard to skip backwards or forwards)."Also, see Goto in Tcl.
