Last Monday I attended Dan Garcia's workshop on BYOB. He kept pointing out
(presumably for the benefit of Emmanuel and me) that it really is a functional
language. And yes, it has "map", "filter", "foldl", and "lambda"... but most
of the examples and assignments one normally does in BYOB use very stateful
turtle graphics. So naturally I thought "Could I simulate this in universe?"
I defined a sprite struct (with an icon, a location, a direction, a pen, etc.)
and a world struct (with a list of sprites and a picture), and wrote a bunch of
low-level operations on these that would obviously be needed. So far so good.
I'm imagining that student code might say something like
; zigzag : sprite -> sprite
(define (zigzag sprite)
(move 10 (rotate-cw 45 (move 10 (rotate-ccw sprite)))))
...
(define this-sprite (make-sprite (bitmap "sprite-icon.png") (make-posn
0 0) 0 ... zigzag)
...
(run-byob-world (list this-sprite that-sprite third-sprite)
initial-background-picture)
which would in turn call big-bang with a prewritten draw handler and a tick
handler that calls each sprite's action on it.
The problem is that some sprite actions (most obviously, "move" when you're in
pen-down mode) affect not only the sprite itself but the world's picture. So
far the least-bad solution I've come up with is to hide a mutation of that
picture inside the otherwise-functional "move" function.
I've experimented with a couple of ways to do that. One way is to define (in
my code, not visible to student code) a box named "world-pic", which is
set-box!ed in "move" and "run-byob-world". Another is to use just a plain
variable and "set!", again hidden inside "move" and "run-byob-world". Both
seem to work for my toy examples so far; is there any advantage of one over the
other? What subtle gotchas am I going to run into? Is "a little bit of
mutation" like "a little bit pregnant?"
Stephen Bloch
[email protected]
_________________________________________________
For list-related administrative tasks:
http://lists.racket-lang.org/listinfo/users