Showing posts with label special variables. Show all posts
Showing posts with label special variables. Show all posts

Friday, February 15, 2008

Faux dynamic binding for Arc

The objective in what follows is to simulate one of my favorite features of CL, which is dynamic binding of special variables. If you ever programmed QuickDraw for the Mac and tediously had to code up GetPort, SetPort, and then a SetPort back when finished drawing, just imagine having the ability simply to code:

(let grafport* (grafPort my-window)
...)

...and get the whole save, re-bind, and restore taken care of for you. Does not come up a lot, but when it does this rocks (and Cells uses it for its core behavior of tracking dependencies). You see this sort of thing especially in cases exactly like the drawing GrafPort, something so fundamental that the lowest level functions will need it so it is either a global of some kind or every function in the API needs it as a parameter.

In the case of Cells, without dynamic binding almost every function in the application would need it. Not a pretty thought.

Caveat emptor: The following has been lightly tested with only one variable pseudo-dynamically bound. Bug reports welcome, but if the report is "Listen, dummy, Arc already has that."...well, I'll just be a normallispweeny for a week:


(mac withs* (parms . body)
(let uparms (map1 [cons (uniq) _] (pair parms))
`(do ,@(map1 (fn ((save curr val))
`(= ,save ,curr ,curr ,val)) uparms)
(do1
(do ,@body)
,@(map1 (fn ((save curr val))
`(= ,curr ,save)) uparms)))))

(= stak* (list 'top))

(def pstack (k)
(prs k stak*)(prn))

(do
(pstack 'start)
(with* (stak* (cons 'me stak*))
(prt 'with-me stak*)
(pstack 'confirm-with-me))
(pstack 'bye-bye))


Output should be:

start (top)
with-me (me top)
confirm-with-me (me top)
bye-bye (top)


Enjoy. (And with* left as an exercise. :)