common lisp - define-modify-macro with operator argument -
in section 12.4 of on lisp, paul graham writes, "unfortunately, can't define correct _f define-modify-macro, because operator applied generalized variable given argument."
but what's wrong this?
(define-modify-macro _f (op operand) (lambda (x op operand) (funcall op x operand))) (let ((lst '(1 2 3))) (_f (second lst) #'* 6) lst) => (1 12 3) has there perhaps been change made define-modify-macro in ansi common lisp wasn't valid @ time on lisp written? or there reasons other 1 stated not using define-modify-macro here?
it appears graham want's able make call such as
(_f * (second lst) 6) rather than
(_f #'* (second lst) 6) but surely that's not in keeping lisp2 such common lisp?
according both lispworks's hyperspec , cltl2 (look define-modify-macro), function assumed symbol (to function or macro). far know, following definition might not conforming specification:
(define-modify-macro _f (op operand) (lambda (x op operand) (funcall op x operand))) but of course, possible implementation allows it. sure conforming standard, can define own function, or macro:
(defmacro funcall-1 (val fun &rest args) `(funcall ,fun ,val ,@args)) (define-modify-macro _ff (&rest args) funcall-1) (let ((x (list 1 2 3 4))) (_ff (third x) #'+ 10) x) if wanted have function second argument, define macro:
(defmacro ff (fun-form place &rest args) `(_ff ,place ,fun-form ,@args)) basically, approach consists in wrapping funcall in define-modify-macro, , give desired function argument of function. @ first sight, looks hack, can see below, gives same macroexanded code 1 in on lisp, assuming modify latter little.
the macroexpansion of above is:
(let ((x (list 1 2 3 4))) (let* ((#:g1164 x) (#:g1165 (funcall #'+ (third #:g1164) 10))) (sb-kernel:%rplaca (cddr #:g1164) #:g1165)) x) the version in on lisp behaves follows:
(defmacro _f (op place &rest args) (multiple-value-bind (vars forms var set access) (get-setf-expansion place) `(let* (,@(mapcar #'list vars forms) (, (car var) (,op ,access ,@args))) ,set))) (let ((x (list 1 2 3 4))) (_f * (third x) 10) x) macroexpansion:
(let ((x (list 1 2 3 4))) (let* ((#:g1174 x) (#:g1175 (* (third #:g1174) 10))) (sb-kernel:%rplaca (cddr #:g1174) #:g1175)) x) here, * injected directly macroexpansion, means resulting code has no possible runtime overhead (though compilers handle (funcall #'+ ...) equally well). if pass #'+ macro, fails macroexpand. major difference approach, not big limitation. in order allow on lisp version accept #'*, or (create-closure) operator, should modified follows:
(defmacro _f (op place &rest args) (multiple-value-bind (vars forms var set access) (get-setf-expansion place) `(let* (,@(mapcar #'list vars forms) (, (car var) (funcall ,op ,access ,@args))) ,set))) (see call funcall)
the previous example expanded follows, #'*:
(let ((x (list 1 2 3 4))) (let* ((#:g1180 x) (#:g1181 (funcall #'* (third #:g1180) 10))) (sb-kernel:%rplaca (cddr #:g1180) #:g1181)) x) now, version. on lisp uses _f demonstrate how use get-setf-expansion, , _f example that. on other hand, implementation seems equally good.
Comments
Post a Comment