[racket] Advice: simulating stateful API in functional setting
On Fri, Jul 15, 2011 at 11:56 AM, Stephen Bloch <sbloch at adelphi.edu> wrote:
> 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.
I see you're already representing the World as a picture and a list of
sprites, so just let the kids manipulate that directly.
Since you want to support multiple sprites, what if each sprite in the
sprite list had a name, so the contract is:
move: String (sprite-name) Integer (distance) World -> World
So:
(define (zigzag sprite-name world)
(move sprite-name 10 (rotate-cw sprite-name 45 (move sprite-name 10
(rotate-ccw sprite-name world)))))
You could also provide functions to add and delete sprites from the world.
add-sprite: String (sprite-name) Posn (start-location) World -> World
delete-sprite: String (sprite-name) World -> World
Then, give them some sort of
blank-canvas
which is a make-world that has an empty list of sprites and an empty
scene as the picture.