Let macros
These are macros that combine a let
or let*
form with a test
based on the results of the bindings. This is useful for reducing
common boilerplate where a let is used to perform some operations, and
some code should be executed based on the results of those bindings.
For example, from kmop/kmop.lisp
:
* (macroexpand-1
'(whenlet ((kwarg (slot-initarg slot))
(value (dispatch-get-value
slot
(slot-table-value
slot ht snake-case))))
(list kwarg value)))
(LET ((KWARG (SLOT-INITARG SLOT))
(VALUE
(DISPATCH-GET-VALUE SLOT
(SLOT-TABLE-VALUE SLOT HT SNAKE-CASE))))
(WHEN (AND KWARG VALUE)
(LIST KWARG VALUE)))
condlet
(bindings &body forms)
bindings
in a let
form, then evaluate forms
in
a cond
.condlet*
(bindings &body forms)
bindings
in a let*
form, then evaluate forms
in
a cond
.iflet
(bindings &body (then &optional else))
bindings
in a let
form; if they are all T, execute
the then
form. Otherwise, execute the else
form.iflet*
(bindings &body (then &optional else))
bindings
in a let*
form; if they are all T, execute
the then
form. Otherwise, execute the else
form.orlet
(bindings &body body)
body
in a progn
.(macroexpand-1
'(orlet ((cls (class-symbol s))
(slots (only-key-slots cls))
(args (json-slots tbl slots)))
(apply #'make-instance cls args)))
(LET ((CLD (CLASS-SYMBOL S)))
(WHEN CLS
(LET ((SLOTS (ONLY-KEY-SLOTS CLS)))
(WHEN SLOTS
(LET ((ARGS (JSON-SLOTS TBL SLOTS)))
(WHEN ARGS
(PROGN (APPLY #'MAKE-INSTANCE CLS ARGS))))))))
unlesslet
(bindings &body body)
body
in an implicit progn
.unlesslet*
(bindings &body body)
bindings
in a let*
form; if they are all not NIL,
evaluate body
, which is wrapped in an implicit progn
.whenlet
(bindings &body body)
body
in an implicit progn
.whenlet*
(bindings &body body)
bindings
in a let*
form; if they all evaluate to T,
evaluate body
, which is wrapped in an implicit progn
.File macros
These macros abstract common operations on files.
with-read-from-file
((stream path &rest args &key (direction input directionp) &allow-other-keys) &body body)
path
for reading, bound to stream
, with any remaining arguments
passed to with-open-file
, and execute body
.with-write-to-file
((stream path &rest args &key (direction output directionp) &allow-other-keys) &body body)
body
with the file at path
opened and bound to the
value of stream
. Any remaining keyword arguments are passed to
with-open-file
.The following two macros aren't yet able to be documented with
Codex, as they are
defined using the defmacro!
macro:
read-file-as-string (path &rest args
&key (direction nil directionp)
&allow-other-keys)
Read the contents of the file at path
as a string. Any remaining
arguments are sent to with-open-file
.
with-string-output-to-file
((path &rest args &key (direction :output directionp)
&allow-other-keys)
&body body)
Evaluate body
, and call mkstr
on the result. Write the
resulting string to path
. Any remaining arguments are sent to
with-open-file
.
General
in
(obj seq &key (test (function eql)) key deep)
Returns T if obj
, is in seq
.
If seq
is a list, test
is used to determine whether the object
matches. If key
is not NIL, it is applied to elements before
test
. If deep
is true, seq
will be flattened before
checking the list.
If seq
is a vector, test
is used to determine whether the
object matches. If key
is not NIL, it is applied to elements
before test
.
If seq
is a hash table, test
does not apply; the hash table's
test is used. If key
is not NIL, it is applied to obj
before
looking it up.