I got more involved with Tcl over time ( http://tcl.apache.org/ and some other stuff) and over the past couple of years have been moving towards Ruby for most of my scripting/web needs.
All I can remember about Tcl from my months of using it is the ugly, ugly loops:
for {set i 1} { $i <= 100 } { incr i } {
puts "Well, that wasn't ugly syntax!"
}
Incidentally, Fortran, for all its other ugliness, has the best for loop I know: do i = 1, 100
write(*,*) "Hooray, Fortran!"
enddoHow is that better than Python?
for i in range( 1, 100 ):
print "Python!" (1..100).each do
puts "Ruby"
end 100.times { puts "Ruby" }
Not that there's anything wrong with your approach, but I just like the way that my code reads almost like English.(Counting only the loop-related characters, leaving out whitespace.)
Unless anyone has a shorter way of doing something one hundred times?
Look, I'm only too familiar with the annoyances of Fortran, but let's allow it this one thing, okay?
>>> for i in range(1000000000):
... print i
...
python2.4(1261) malloc: *** vm_allocate(size=4000002048) failed (error code=3)
python2.4(1261) malloc: *** error: can't allocate region
python2.4(1261) malloc: *** set a breakpoint in szone_error to debug
Traceback (most recent call last):
File "<stdin>", line 1, in ?
MemoryError
Why attempt to allocate such a large list when you just want to do something several times?xrange() addresses the problem you describe and has been in Python since, like, forever. However, range() is nicer for learning the language, since it's easy to see how it composes into a list.
http://antirez.com/articoli/tclmisunderstood.html
'for' is a command that takes 4 arguments:
{set i 1} - eval'ed once at start time.
{ $i <= 100 } - an expression that is checked each time to determine whether to continue
{ incr i } - eval'ed each time
{ ... the rest ... } the body is eval'ed each time.
Everything in Tcl is like that - it's extremely easy to figure out and there are no surprises. It's also extremely easy to implement. Here's Hecl's for loop: case FOR:
/* The 'for' command. */
/* start */
interp.eval(argv[1]);
/* test */
while (Thing.isTrue(interp.eval(argv[2]))) {
try {
/* body */
interp.eval(argv[4]);
} catch (HeclException e) {
if (e.code.equals(HeclException.BREAK)) {
break;
} else if (e.code.equals(HeclException.CONTINUE)) {
} else {
throw e;
}
}
/* next */
interp.eval(argv[3]);
}
break;