[plt-scheme] Re: Continuations memory accumulation problem
Hey! Only now it struck me what the following code is doing (I
initially thought it's some kind of twisted syntax trickery)... :)
~~~~
(define ((do-when pred? action) s)
(if (pred? s) (action s) s))
~~~~
it's equivalent with
~~~~
(define (do-when pred? action)
(define (__anonymous__ state)
(if (pred? state) (action state) state))
__anonymous__)
~~~~
I have to admit that (PLT) Scheme is very powerful! (I don't
actually thing that this is possible (out of the box) in Common
Lisp...) :)
And if we are at this chapter, I also want to praise the ones that
have introduced the `for` family of iterations, which (especially
for/list) actually covers most `map` use cases.
It seems that I never finish learning.
Ciprian.
On Mon, Mar 15, 2010 at 10:37 PM, Anthony Cowley <acowley at seas.upenn.edu> wrote:
> [... a lot of snip, snip ... ]
>
> Anthony
>
> [... some snip, snip ...]
>
> --------------
>
> #lang scheme
>
> ;; 2D position
> (define-struct pos (x y) #:transparent)
>
> ;; A robot has a position, a heading, and a list of transient actions.
> (define-struct (robot pos) (θ action) #:transparent)
>
> ;; Add a transient action to a robot's state.
> (define ((add-action a) r)
> (struct-copy robot r (action (cons a (robot-action r)))))
>
> ;; Move a robot straight ahead at unit velocity.
> (define (move-ahead r)
> (make-robot (+ (pos-x r) (cos (robot-θ r)))
> (+ (pos-y r) (sin (robot-θ r)))
> (robot-θ r)
> (robot-action r)))
>
> ;; Choose a random new heading for a robot.
> (define (assume-random-heading r)
> (struct-copy robot r (θ (* (random) 2 pi))))
>
> ;; The simulation world has an enemy and a food item.
> (define enemy (make-pos 2 3))
> (define food (make-pos 6 7))
>
> ;; Proximity predicate.
> (define ((near? item dist) robot)
> (let ((dx (- (pos-x item) (pos-x robot)))
> (dy (- (pos-y item) (pos-y robot))))
> (< (sqrt (+ (* dx dx) (* dy dy))) dist)))
>
> (define near-enemy? (near? enemy 5))
> (define near-food? (near? food 2))
>
> ;; If the predicate evaluates to true when applied to a state value,
> ;; return the result of applying the action to that state value.
> ;; Otherwise, return the state value unchanged.
> (define ((do-when pred? action) s) (if (pred? s) (action s) s))
>
> ;; If-then-else combinator for state modification.
> (define ((do-if pred? then else) s) (if (pred? s) (then s) (else s)))
>
> ;; Zap a nearby enemy.
> (define zap (do-when near-enemy? (add-action 'zap)))
>
> ;; Grab a nearby food item.
> (define grab (do-when near-food? (add-action 'grab)))
>
> ;; Move ahead if otherwise unoccupied, but periodically pick a
> ;; random new heading.
> (define wander (do-when (compose null? robot-action)
> (do-if (λ (_) (= (random 10) 0))
> assume-random-heading
> move-ahead)))
>
> ;; Execute the behavior stack. A robot will zap a nearby enemy,
> ;; grab a nearby food item, or just wander around.
> (define (simulate-robot r)
> (foldl (λ(f r) (f r)) r (list zap grab wander)))
>
> ;; Reset the robot's transient state.
> (define (reset-action r) (struct-copy robot r (action '())))
>
> ;; Draw a robot, and reset its transient actions.
> (define (viz r) (printf "~a~n" r) (reset-action r))
>
> ;; Run a simulation iteration.
> (define (run-simulation robots)
> (map (compose viz simulate-robot) robots))
>
> (define (test)
> (let ((robots (list (make-robot 3 3 pi '())
> (make-robot 5 6 0 '())
> (make-robot 12 11 (* pi 0.5) '()))))
> (run-simulation robots)))