I have a function called use
which accepts an arbitrary number of keyword arguments (as a plist) defined as below:
(defun use (&rest plist &key &allow-other-keys)
":href should be supplied, as it is the path/to/svg#id to be used."
;; Hole die Sachen die wichtig sind aus der PListe
(let ((href (getf plist :href "#")))
;; Remove :href otherwise it appears in the plist again!
(remf-indicators-from-plist '(:href) plist)
(list plist href)
))
Here i extract some keyword arguments which are important and should be specified by the user, and then remove them from the plist of supplied keyword arguments with the remf-indicators-from-plist
, so that i don't process them twice. remf-indicators-from-plist
is defined below:
(defun remf-indicators-from-plist (indicators plist)
"Removes indicators from the plist,
to prevent callers from double-using them."
(dolist (indicator indicators plist)
(remf plist indicator)))
Now it seems to me if the keyword argument/s i want to extract in the use
function and then remove, are indeed removed if they appear not as the first parameter to the function:
(use :x 34 :href 23 :c2 32) ;((:X 34 :C2 32) 23)
(use :x 34 :c2 32 :href 23) ;((:X 34 :C2 32) 23)
but not if it appears as the first parameter:
(use :href 23 :x 34 :c2 32) ;((:HREF 23 :X 34 :C2 32) 23)
Why is this? And how can i implement it correctly?
The problem is in the function use
, while remf-indicators-from-plist
works correctly.
The reason is that the function remf-indicators-from-plist
returns the list modified (inside the dolist
), but the value returned is discarded inside use
. A possible solution is to change the definition of use
for instance as:
CL-USER> (defun use (&rest plist &key &allow-other-keys)
":href should be supplied, as it is the path/to/svg#id to be used."
;; Hole die Sachen die wichtig sind aus der PListe
(let ((href (getf plist :href "#"))
(new-plist (remf-indicators-from-plist '(:href) plist)))
(list new-plist href)))
USE
CL-USER> (use :x 34 :href 23 :c2 32)
((:X 34 :C2 32) 23)
CL-USER> (use :href 23 :x 34 :c2 32)
((:X 34 :C2 32) 23)
The fact that when :href
is inside the plist everything apparently works, is due to the particular way side-effects are performed by certain operations in Common Lisp. A rule that help in managing side-effecting operations (a part from the fact that constant data should never be modified) is the following: always returns the structure that is modified, even if the modifications seems to happen “in place”.