I thought the do in in Scheme was a li’l hard to learn since the
examples I could find was a li’l too fancy and clever. Just like a lot
of my own documentation often is; sorry about that.
(do ((a 0 (add1 a))
(e 13)
(i 7 (sub1 i)))
((zero? i) (print "ended ") (print a))
(print "game cube")
(print e)
(print a " wii"))
The first argument is a list of bindings like a let. But if you put in
three things they will be rebind every round. Like in the above
example, a will be rebound to (add1 a), and s will be rebound to
(sub1 s). And you can also put in just one thing like the example
here just binds e to 13 and then it just stays that.
The second argument is a list that starts with the ending condition and the rest of the list are statements that will be evaled after.
And then all the remaining arguments are evaled every round.
Yes, this is backwards that the ending stuff comes before the main progn body.
Here’s a more basic example to just print happy birthday four times:
(do ((i 4 (sub1 i)))
((zero? i))
(print "happy birthday"))
Although for simple things like that, Chicken has dotimes:
(dotimes (i 4) (print "happy birthday"))
Both do and dotimes are pretty side-effects oriented but in both cases you can put in a return value:
(do ((i 4 (sub1 i)))
((zero? i) 'my-return-value)
(print "happy birthday"))
(dotimes (i 4 'my-return-value) (print "happy birthday"))
And that return value can access your do scoped binds.
I refer to my own fold write-up all the time (the
folds as named lets version hasn’t been as useful) and maybe with
this, I can use do and dotimes more instead of making let loops
and consing up unnecessary iotas.