Add some macros.

* Add a variety of let-based macros to abstract common patterns.
This commit is contained in:
Kyle Isom 2015-08-31 20:41:57 -07:00
parent d3b8cb6d26
commit 4cb1950c5f
3 changed files with 142 additions and 0 deletions

View File

@ -194,6 +194,36 @@ will be returned as an alist:
@end(section) @end(section)
@begin(section)
@title(Macros)
@begin(deflist)
@term(Let macros)
@begin(def)
These are macros that combine a @c(let) or @c(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.
@cl:with-package[name="kutils"](
@cl:doc(macro condlet)
@cl:doc(macro condlet*)
@cl:doc(macro iflet)
@cl:doc(macro iflet*)
@cl:doc(macro unlesslet)
@cl:doc(macro unlesslet*)
@cl:doc(macro whenlet)
@cl:doc(macro whenlet*)
)
@end(def)
@end(deflist)
@end(section)
@begin(section) @begin(section)
@title(Symbol index) @title(Symbol index)
@ -220,6 +250,12 @@ described in "Miscellaneous utilities" under "General".)
@item(@c(compose) is a function defined in @c(on.lisp), described in @item(@c(compose) is a function defined in @c(on.lisp), described in
"On Lisp utilities".) "On Lisp utilities".)
@item(@c(condlet) is a macro defined in @c(macros.lisp), described in
"Macros".)
@item(@c(condlet*) is a macro defined in @c(macros.lisp), described in
"Macros".)
@item(@c(copy-hash-table) is a function defined in @item(@c(copy-hash-table) is a function defined in
@c(kutils-hash-tables.lisp), described in "Hash-table related @c(kutils-hash-tables.lisp), described in "Hash-table related
utilities".) utilities".)
@ -257,6 +293,12 @@ utilities".)
@c(kutils-hash-tables.lisp), described in "Hash-table related @c(kutils-hash-tables.lisp), described in "Hash-table related
utilities".) utilities".)
@item(@c(iflet) is a macro defined in @c(macros.lisp), described in
"Macros".)
@item(@c(iflet*) is a macro defined in @c(macros.lisp), described in
"Macros".)
@item(@c(interpose) is a function defined in @c(kutils.lisp), @item(@c(interpose) is a function defined in @c(kutils.lisp),
described in "Miscellaneous utilities" under "Clojure-inspired described in "Miscellaneous utilities" under "Clojure-inspired
functions".) functions".)
@ -295,6 +337,18 @@ Lisp utilities".)
@item(@c(take) is a function defined in @c(kutils.lisp), described in @item(@c(take) is a function defined in @c(kutils.lisp), described in
"Miscellaneous utilities" under "Clojure-inspired functions".) "Miscellaneous utilities" under "Clojure-inspired functions".)
@item(@c(unlesslet) is a macro defined in @c(macros.lisp), described in
"Macros".)
@item(@c(unlesslet*) is a macro defined in @c(macros.lisp), described in
"Macros".)
@item(@c(whenlet) is a macro defined in @c(macros.lisp), described in
"Macros".)
@item(@c(whenlet*) is a macro defined in @c(macros.lisp), described in
"Macros".)
@item(@c(with-new-hash-table) is a macro defined in @item(@c(with-new-hash-table) is a macro defined in
@c(kutils-hash-tables.lisp), described in "Hash-table related @c(kutils-hash-tables.lisp), described in "Hash-table related
utilities".) utilities".)
@ -318,6 +372,8 @@ Alphabetical documentation for all exported symbols.
@cl:doc(function build-vector) @cl:doc(function build-vector)
@cl:doc(function cartprod2) @cl:doc(function cartprod2)
@cl:doc(function compose) @cl:doc(function compose)
@cl:doc(macro condlet)
@cl:doc(macro condlet*)
@cl:doc(function copy-hash-table) @cl:doc(function copy-hash-table)
@cl:doc(macro defmacro!) @cl:doc(macro defmacro!)
@cl:doc(function drop) @cl:doc(function drop)
@ -329,6 +385,8 @@ Alphabetical documentation for all exported symbols.
@cl:doc(function group) @cl:doc(function group)
@cl:doc(function hash-table-to-alist) @cl:doc(function hash-table-to-alist)
@cl:doc(function hashkeys) @cl:doc(function hashkeys)
@cl:doc(macro iflet)
@cl:doc(macro iflet*)
@cl:doc(function interpose) @cl:doc(function interpose)
@cl:doc(function macroexpand-n) @cl:doc(function macroexpand-n)
@cl:doc(macro mapv) @cl:doc(macro mapv)
@ -341,6 +399,10 @@ Alphabetical documentation for all exported symbols.
@cl:doc(macro sethash) @cl:doc(macro sethash)
@cl:doc(function symb) @cl:doc(function symb)
@cl:doc(function take) @cl:doc(function take)
@cl:doc(macro unlesslet)
@cl:doc(macro unlesslet*)
@cl:doc(macro whenlet)
@cl:doc(macro whenlet*)
@cl:doc(macro with-new-hash-table) @cl:doc(macro with-new-hash-table)
@cl:doc(function zip)) @cl:doc(function zip))

70
macros.lisp Normal file
View File

@ -0,0 +1,70 @@
;;;; macros.lisp
(in-package #:kutils)
;;; Various utility macros.
(defmacro when (bindings &body body)
"Evaluate the bindings in a let form; if they all evaluate to T,
evaluate @c(body) in an implicit @c(progn)."
(let ((bindings (if (listp (first bindings)) bindings (list bindings))))
`(let (,@bindings)
(when (and ,@(mapcar #'first bindings))
,@body))))
(defmacro whenlet* (bindings &body body)
"Evaluate @c(bindings) in a @c(let*) form; if they all evaluate to T,
evaluate @c(body), which is wrapped in an implicit @c(progn)."
(let ((bindings (if (listp (first bindings)) bindings (list bindings))))
`(let* (,@bindings)
(when (and ,@(mapcar #'first bindings))
,@body))))
(defmacro unlesslet (bindings &body body)
"Evaluate the bindings in a let form; if they don't all evaluate to T,
evaluate @c(body) in an implicit @c(progn)."
(let ((bindings (if (listp (first bindings)) bindings (list bindings))))
`(let (,@bindings)
(unless (and ,@(mapcar #'first bindings))
,@body))))
(defmacro unlesslet* (bindings &body body)
"Evaluate @c(bindings) in a @c(let*) form; if they are all not NIL,
evaluate @c(body), which is wrapped in an implicit @c(progn)."
(let ((bindings (if (listp (first bindings)) bindings (list bindings))))
`(let* (,@bindings)
(unless (and ,@(mapcar #'first bindings))
,@body))))
(defmacro iflet (bindings &body (then &optional else))
"Evaluate @c(bindings) in a @c(let) form; if they are all T, execute
the @c(then) form. Otherwise, execute the @c(else) form."
(let ((bindings (if (listp (first bindings)) bindings (list bindings))))
`(let* (,@bindings)
(if (and ,@(mapcar #'first bindings))
(progn ,then)
(progn ,else)))))
(defmacro iflet* (bindings &body (then &optional else))
"Evaluate @c(bindings) in a @c(let*) form; if they are all T, execute
the @c(then) form. Otherwise, execute the @c(else) form."
(let ((bindings (if (listp (first bindings)) bindings (list bindings))))
`(let* (,@bindings)
(if (and ,@(mapcar #'first bindings))
(progn ,then)
(progn ,else)))))
(defmacro condlet (bindings &body forms)
"Evaluate @c(bindings) in a @c(let) form, then evaluate @c(forms) in
a @c(cond)."
(let ((bindings (if (listp (first bindings)) bindings (list bindings))))
`(let (,@bindings)
(cond ,@forms))))
(defmacro condlet* (bindings &body forms)
"Evaluate @c(bindings) in a @c(let*) form, then evaluate @c(forms) in
a @c(cond)."
(let ((bindings (if (listp (first bindings)) bindings (list bindings))))
`(let (,@bindings)
(cond ,@forms))))

View File

@ -40,4 +40,14 @@
#:copy-hash-table #:copy-hash-table
#:hash-table-to-alist #:hash-table-to-alist
#:alist-to-hash-table #:alist-to-hash-table
;; macros.lisp
#:whenlet
#:whenlet*
#:unlesslet
#:unlesslet*
#:iflet
#:iflet*
#:condlet
#:condlet*
)) ))