Is is possible to treat a key as true when using cl-defmacro
s in elisp? For example,
(cl-defmacro mac (&key a b c)
`(,@(if a "a" (if b "b" "c"))))
(mac :a)
"c"
Can I have that evaluate to "a" without needing to give :a
a value like (mac :a t
). I don't know if the same semantics apply to common-lisp
There is no way to do this with the base language. One could define a defun
like macro to do this. Would you want to only allow these to be set to true or would you want to give values other than t
(or nil
be omission)? The first case can be done by writing some macros. The second case can’t be done in a nice way (specifically would (mac :a :b)
do a <- t; b <- t
or a <- :b
?)
Here is something you could write for Common Lisp:
(defmacro keyset-bind (keys-and-vars form &body body)
(let (syms vars
(keyv (gensym "KEY")))
(loop for key in keys-and-vars
for sym = (if (consp key)
(car key)
(intern (symbol-name key) "KEYWORD"))
for var = (if (consp key) (cadr key) key)
collect sym into symst
collect var into varst
finally (setf syms symst vars varst))
`(let ,vars
(loop for ,keyv in ,form
do (case ,keyv
,@(loop for sym in syms
for var in vars
collect `((,sym) (setf ,var t)))
(t (error "unrecognised keyword ~a" ,keyv))))
,@body)))
And then you can use it like:
(defun mac (&rest switches)
(keyset-bind (a b (:t foo)) switches
(list a b foo)))
CL-USER> (mac :a)
(T NIL NIL)
CL-USER> (mac :b :t)
(NIL NIL T)
CL-USER> (mac :baz)
;; Error ...
One could write an alternative defun
which accepted eg a &switch
argument type in this way but then you would need to decide how to make it interact with other argument types and keywords and &allow-other-keys
and :allow-other-keys t
. In general all of this is a bad idea and any kind of mixing with (or even usage of) the above is discouraged as it makes it hard to know whether an unfamiliar function call will be interpreted as normal keywords or set-of-keywords. If you want a language which supports this kind of thing, look at perl6 where keywords are a key-value-pair type and there is special syntax for key => true
and key => false
.