kutils ยป Macros

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)
Evaluate bindings in a let form, then evaluate forms in a cond.
condlet*(bindings &body forms)
Evaluate bindings in a let* form, then evaluate forms in a cond.
iflet(bindings &body (then &optional else))
Evaluate 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))
Evaluate bindings in a let* form; if they are all T, execute the then form. Otherwise, execute the else form.
orlet(bindings &body body)
For each set of bindings, evaluate them in sequence. If each binding evaluates to T, evaluate 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)
Evaluate the bindings in a let form; if they don't all evaluate to T, evaluate body in an implicit progn.
unlesslet*(bindings &body body)
Evaluate bindings in a let* form; if they are all not NIL, evaluate body, which is wrapped in an implicit progn.
whenlet(bindings &body body)
Evaluate the bindings in a let form; if they all evaluate to T, evaluate body in an implicit progn.
whenlet*(bindings &body body)
Evaluate 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)
Open 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)
Evaluate 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.