Re: define-modify-macro bug?
Roger Corman <[email protected]> Mon, 17 Nov 2003 12:04:19 -0800
| Newsgroups | gmane.lisp.corman |
|---|---|
| Message-ID | <[email protected]> |
Hi Dan,
Thanks for the bug report, and the fixed version. Nested backquotes make my head hurt as well. :-)
Rather than use your modified version, which I haven't had time to analyze, I suggest replacing the one in corman lisp with the CMU version, which is public domain. I will probably post a patch with this file changed (sys/control-structures.lisp). Here is the adapted version of the CMU function. It takes care of other things as well, and has some good error checking. If anybody notices any problems with this please let me know. It works for all the examples I have tried.
Roger
;;;
;;; Common Lisp DEFINE-MODIFY-MACRO function.
;;; Adapted from CMU Lisp.
;;;
(defmacro define-modify-macro (name lambda-list function &optional
doc-string)
"Creates a new read-modify-write macro like PUSH or INCF."
(let ((other-args nil)
(rest-arg nil)
(env (gensym))
(reference (gensym)))
(do ((ll lambda-list (cdr ll)) (arg nil))
((null ll))
(setq arg (car ll))
(cond ((eq arg '&optional))
((eq arg '&rest)
(if (symbolp (cadr ll))
(setq rest-arg (cadr ll))
(error "Non-symbol &rest arg in definition of ~S."
name))
(if (null (cddr ll))
(return nil)
(error "Illegal stuff after &rest arg in DEFINE-MODIFY-MACRO.")))
((member arg '(&key &allow-other-keys &aux) :test 'eq)
(error "~S not allowed in DEFINE-MODIFY-MACRO lambda list."
arg))
((symbolp arg) (push arg other-args))
((and (listp arg) (symbolp (car arg)))
(push (car arg) other-args))
(t
(error "Illegal stuff in lambda list of DEFINE-MODIFY-MACRO."))))
(setq other-args (nreverse other-args))
`(defmacro ,name (,reference ,@lambda-list &environment ,env)
,doc-string
(multiple-value-bind (dummies vals newval setter getter)
(get-setf-expansion ,reference ,env)
(do ((d dummies (cdr d))
(v vals (cdr v))
(let-list nil (cons (list (car d) (car v)) let-list)))
((null d)
(push (list (car newval)
,(if rest-arg
`(list* ',function
getter
,@other-args
,rest-arg)
`(list ',function
getter
,@other-args)))
let-list)
`(let* (common-lisp::%comma (nreverse let-list))
,setter)) )))))
-------------------------------------------------------------------
At 03:11 PM 11/16/2003, you wrote:
>On 16 Nov 2003 at 16:45, Dan Muller afjeccf02-at-sneakemail.com |Y wrote:
>
>> Is this a bug in Corman Lisp 2.5? This example is very similar to one
>> given in the Hyperspec, and the definition of appendf also exists in the
>> version of ASDF that I am trying to use:
>>
>> ?(define-modify-macro appendf (&rest args)
>> append "Append onto list")
>> ;;; Warning: Symbol &REST assumed special
>> APPENDF
>> ?(setq x '(a b c))
>> (A B C)
>> ?(appendf x '(d e f) '(1 2 3))
>> ;;; An error occurred in function MACROEXPAND:
>> ;;; Error: The variable &REST is unbound
>> ;;; Entering Corman Lisp debug loop.
>> ;;; Use :C followed by an option to exit. Type :HELP for help.
>> ;;; Restart options:
>> ;;; 1 Abort to top level.
>> :c 1
>> ;;; Returning to top level loop.
>> ?
>>
>Working from the assumption that the above is in fact a bug, I thought it would be an
>interesting exercise to try to fix it, seeing as I haven't written any non-trivial macros yet. I
>started from the definition in sys/control-structures.lisp, and came up with the following
>modified version, which seems to work:
>
>(defmacro define-modify-macro (name lambda-list function &optional documentation)
> (let ((place (gensym))
> reg-args
> rest-arg)
> (flet ((get-args (ll)
> (cond ((null ll) t)
> ((eq (car ll) '&rest) (setq rest-arg (cadr ll)))
> ((eq (car ll) '&optional) (get-args (cdr ll)))
> (t (push (car ll) reg-args)))))
> (get-args lambda-list)
> `(defmacro ,name (,place ,@lambda-list &environment env)
> ,@(if documentation (list documentation))
> (multiple-value-bind (vars vals new setter getter)
> (get-setf-expansion ,place env)
> (declare (ignore setter))
> `(let* (,@(mapcar 'list vars vals) (,(car new) ,getter))
> (setf ,getter (funcall (function ,',function) ,(car new) ,,@reg-args ,@,rest-
>arg))))))))
>
>
>Critiques are welcome. The nested backquote form at the end makes my head hurt; I'm
>not sure I understand exactly *why* splicing rest-arg in using ,@, works.
>
>I don't think this is going to let me use ASDF with Corman Lisp, yet, though. There is a
>dependence on make-broadcast-stream, which doesn't seem to be defined in Corman
>Lisp 2.5.
>
>
>
>To unsubscribe from this group, send an email to:
>[email protected]
>
>
>
>Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
------------------------ Yahoo! Groups Sponsor ---------------------~-->
Buy Ink Cartridges or Refill Kits for your HP, Epson, Canon or Lexmark
Printer at MyInks.com. Free s/h on orders $50 or more to the US & Canada.
http://www.c1tracking.com/l.asp?cid=5511
http://us.click.yahoo.com/mOAaAA/3exGAA/qnsNAA/SyjtlB/TM
---------------------------------------------------------------------~->
To unsubscribe from this group, send an email to:
[email protected]
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/