I'm looking for a way to modify a property value in a property list by multiplying it with a given factor similar to using incf for adding to a value.
With incf I could say:
(let ((seq '(:x 10 :y 3)))
(incf (getf seq :y) 3)
seq)
-> (:x 10 :y 5)
Using a macro I could obtain the result in the following way, but this uses getf twice:
(defmacro multf (place val)
`(setf ,place (* ,place ,val)))
(let ((seq '(:x 10 :y 3)))
(multf (getf seq :y) 2)
seq)
-> (:x 10 :y 6)
How would I do this so that I could obtain the same result using getf only once?
Maybe there are packages with this functionality, but I couldn't find it in the net. Any help is appreciated! This is no homework, I'm just trying to optimize my code and I'm curious to better understand the language. I read about setf-expanders and compiler-macros, but I don't know whether they apply here and how to make use of them.
but this uses getf twice
the first is a SETF form and the second one is a getter. The first one will be expanded by SETF.
A short definition of multf
using define-modify-macro might be:
CL-USER 28 > (define-modify-macro multf (&optional (number 1)) *)
MULTF
CL-USER 29 > (let ((seq '(:x 10 :y 3)))
(multf (getf seq :y) 2)
seq)
(:X 10 :Y 6)
The full expansion in LispWorks looks like this:
(LET ((SEQ '(:X 10 :Y 3)))
(LET* ((#:G1158 :Y))
(LET* ()
(LET ((#:G1157 (* (GETF SEQ #:G1158) 2)))
(LET ((#:|Store-Var-1156| (SYSTEM::PRIMITIVE-PUTF SEQ #:G1158 #:G1157)))
(SETQ SEQ #:|Store-Var-1156|)
#:G1157))))
SEQ)