Getting functional Common Lisp code for handling state in a SDL animation The following code draws a red rectangle bouncing between the borders of a white display. I'm not particularly happy with the update function:

(require 'lispbuilder-sdl)

(defun update-h-speed (state h-border top-left-border)
  (if (or (&lt; (cdr (assoc 'h-coord state)) top-left-border) ;;if too left
      (&gt; (cdr (assoc 'h-coord state)) h-border))       ;;if too right
      ;; negate the horizontal speed
      (acons 'h-speed (- (cdr (assoc 'h-speed state))) state)
      state))

(defun update-v-speed (state v-border top-left-border)
  (if (or (&lt; (cdr (assoc 'v-coord state)) top-left-border) ;;if too high
      (&gt; (cdr (assoc 'v-coord state)) v-border))       ;;if too low
      ;; negate the vertical speed
      (acons 'v-speed (- (cdr (assoc 'v-speed state))) state)
      state))

(defun update-coords (state)
  (acons 'h-coord (+ (cdr (assoc 'h-coord state))
               (cdr (assoc 'h-speed state)))
       (acons 'v-coord (+ (cdr (assoc 'v-coord state))
                  (cdr (assoc 'v-speed state))) state)))

(defun update (state width height size)
  (let ((h-border (- width (/ size 2)))
    (v-border (- height (/ size 2)))
    (top-left-border (/ size 2)))
    (update-coords
     (update-h-speed
      (update-v-speed state v-border top-left-border) h-border top-left-border))))

(defun game (&amp;optional (width 320) (height 240) (speed 2) (size 20))
  (let ((decoy (pairlis (list 'h-coord 'v-coord 'h-speed 'v-speed)
            (list (/ width 2) (/ height 2) speed speed))))
    (sdl:with-init ()
      (sdl:window width height :title-caption "My game")
      (setf (sdl:frame-rate) 60)
      (sdl:with-events ()
    (:quit-event () t)
    (:key-down-event (:key key)
             (when (sdl:key= key :sdl-key-escape) (sdl:push-quit-event)))
    (:idle ()
           ;; update state
           (setq decoy (update decoy width height size))
           (sdl:clear-display sdl:*white*)
           ;; draw the rectangle according to the updated state
           (sdl:draw-box (sdl:rectangle-from-midpoint-*
                  (cdr (assoc 'h-coord decoy)) (cdr (assoc 'v-coord decoy)) size size)
                 :color sdl:*red*)
           (sdl:update-display))))))


In fact, the big-bang function in Racket made such things quite easy. With big-bang, I usually created a structure to hold every object (just coordinates and speeds of the rectangles) and modified each part of the structure with separate functions.

Please note that this is not a question about making this animation work.

1) I would like to get advice about, how to refactor such programs to make the update function more functional, so that it is easier to expand (add new features) and debug.

2) I'm particularly confused about whether I should prefer special variables to hold the structures, or prefer to create them locally as is the case. Do you prefer one over the other during different cycles of programming (like development and distribution)?

Note: I preferred an assoc list in place of a hash table, because of the few number of pairs, and the acons enables a sort of history feature, if this thing will ever going to work.
I would use CLOS for that. The game state is an CLOS object then. If the thing needs a history, then I would add the history to the CLOS object.

Named slots of something in the history of Lisp:


assoc lists (ca. 1960)
hash-tables
structures (70s)
classes (70s/80s...)


If you look at your update a few things don't look nice:


progn is not needed
way to many SETQs, construct a return value instead
the use of an association list, where a CLOS object should have been used
no explicit return value




(defun update-coords (state)
  (acons 'h-coord (+ (cdr (assoc 'h-coord state))
                     (cdr (assoc 'h-speed state)))
         (acons 'v-coord (+ (cdr (assoc 'v-coord state))
                            (cdr (assoc 'v-speed state)))
                state)))


Sometimes I would want to get rid of the nesting in above function.

(defun update-coords (state)
  (list* (cons 'h-coord (+ (cdr (assoc 'h-coord state))
                           (cdr (assoc 'h-speed state))))
         (cons 'v-coord (+ (cdr (assoc 'v-coord state))
                           (cdr (assoc 'v-speed state))))
         state))


Alternatively you can use the backquote notation. , evaluates. ,@ evaluates and splices the result in.

(defun update-coords (state)
  `((h-coord . ,(+ (cdr (assoc 'h-coord state))
                   (cdr (assoc 'h-speed state))))
    (v-coord . ,(+ (cdr (assoc 'v-coord state))
                   (cdr (assoc 'v-speed state))))
    ,@state))




I would add Practical Common Lisp by Peter Seibel to the reading list. It teaches a larger subset of more idiomatic Common Lisp than for example On Lisp.



With CLOS the code looks much simpler. Example without history:

(defclass game-state ()
  (h-coord v-coord h-speed v-speed))

(defmethod update-coords ((state game-state))
  (with-slots (h-coord h-speed v-coord v-speed)
      state
    (incf h-coord h-speed)
    (incf v-coord v-speed))
  state)