[racket] Advice: simulating stateful API in functional setting

From: Stephen Bloch (sbloch at adelphi.edu)
Date: Fri Jul 15 14:56:15 EDT 2011

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
sbloch at adelphi.edu

Posted on the users mailing list.