Tomasz Wegrzanowski said:
So, how would such a macro look like ?
Well, 1) This is ruby-talk, not comp.lang.lisp, and 2) I don't
actually know lisp.
But how hard can it be, right? .... (1.5 hours later) ....
Okay, try this:
(defun local-expander (bodylist)
(cond ((null bodylist) '())
((and (consp (car bodylist)) (eq (caar bodylist) 'local))
`((let ,(loop for x on (cdar bodylist)
by #'cddr
collect (list (car x) (cadr x)))
,@(local-expander (cdr bodylist)))))
(t (cons (car bodylist) (local-expander (cdr bodylist))))))
(defmacro progn-with-local (&rest body)
`(progn ,@(local-expander body)))
(defmacro defun-with-local (name args &rest body)
`(defun ,name ,args ,@(local-expander body)))
Then, you can do:
(defun-with-local pythag (x y)
(local x2 (* x x))
(local y2 (* y y))
(local z2 (+ x2 y2))
(sqrt z2))
Actually, you could even shorten that slightly to:
(defun-with-local pythag (x y)
(local x2 (* x x) y2 (* y y))
(local z2 (+ x2 y2))
(sqrt z2))
But I think that hurts the readability.
Note that you don't need to supply an initial value in the (local)
bit. Also, a (local) declaration will shadow references that follow
it, but not those that precede it. For example:
* (defvar a 'top)
A
* a
TOP
* (progn-with-local (setf a 'before) (local a) (setf a 'after))
AFTER
* a
BEFORE