From 5847a6b0548b3c99056a867fa053015dfe3754a5 Mon Sep 17 00:00:00 2001 From: Kyle Date: Wed, 2 Sep 2015 00:12:42 -0700 Subject: [PATCH] Add with-gensyms and in macros. --- docs/manual.scr | 16 ++++++++++++++-- macros.lisp | 29 +++++++++++++++++++++++++++++ on.lisp | 9 +++++++++ package.lisp | 2 ++ 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/docs/manual.scr b/docs/manual.scr index a6ec979..d39232b 100644 --- a/docs/manual.scr +++ b/docs/manual.scr @@ -87,6 +87,7 @@ some functions I found useful.) @cl:doc(function group) @cl:doc(function flatten) @cl:doc(function compose) +@cl:doc(macro with-gensyms) ) @@ -263,10 +264,13 @@ Evaluate @c(body), and call @c(mkstr) on the result. Write the resulting string to @c(path). Any remaining arguments are sent to @c(with-open-file). - - @end(def) +@term(General) + +@cl:with-package[name="kutils"]( +@cl:doc(macro in)) + @end(deflist) @end(section) @@ -373,6 +377,9 @@ utilities".) @item(@c(iflet*) is a macro defined in @c(macros.lisp), described in "Macros" under "Let macros".) +@item(@c(in) is a macro defined in @c(macros.lisp), described in +"Macros" under "General".) + @item(@c(interpose) is a function defined in @c(kutils.lisp), described in "Miscellaneous utilities" under "Clojure-inspired functions".) @@ -433,6 +440,9 @@ Lisp utilities".) @item(@c(whenlet*) is a macro defined in @c(macros.lisp), described in "Macros" under "Let macros".) +@item(@c(with-gensyms) is a macro defined in @c(on.lisp), described in +"On Lisp utilities".) + @item(@c(with-new-hash-table) is a macro defined in @c(kutils-hash-tables.lisp), described in "Hash-table related utilities".) @@ -480,6 +490,7 @@ Alphabetical documentation for all exported symbols. @cl:doc(function hashkeys) @cl:doc(macro iflet) @cl:doc(macro iflet*) +@cl:doc(macro in) @cl:doc(function interpose) @cl:doc(function macroexpand-n) @cl:doc(macro mapv) @@ -497,6 +508,7 @@ Alphabetical documentation for all exported symbols. @cl:doc(macro unlesslet*) @cl:doc(macro whenlet) @cl:doc(macro whenlet*) +@cl:doc(macro with-gensyms) @cl:doc(macro with-new-hash-table) @cl:doc(macro with-read-from-file) @cl:doc(macro with-write-to-file) diff --git a/macros.lisp b/macros.lisp index 3de880e..4e6acbb 100644 --- a/macros.lisp +++ b/macros.lisp @@ -113,3 +113,32 @@ value of @c(stream). Any remaining keyword arguments are passed to (error "Specifying :direction is not allowed with WRITE-FILE.")) `(with-open-file (,stream ,path :direction ,direction ,@args) ,@body)) + +(defun is (a b test key) + "Are a and b equal? If not NIL, #'key is applied to b, then #'test +is called on both." + (declare (inline)) + (funcall test + (if key + (funcall key b) + b) + a)) + +(defmacro in (obj seq &key (test #'eql) key deep) + "Returns T if @c(obj), which may be a vector or list), is in +@c(seq); using @c(test) to determine whether the object matches. If +@c(key) is not NIL, it is applied to the key before @c(test). If +@c(deep) is true, @c(seq) will be flattened before checking the +list. Note that @c(deep) is only valid for lists, and will not behave +as expected with vectors." + (with-gensyms (obj% seq% x!) + (declare (dynamic-extent obj% seq% x!)) + `(let ((,obj% ,obj) + (,seq% (if ,deep ,(flatten seq) ,seq))) + (cond + ((vectorp ,seq%) + (loop for ,x! across ,seq% + thereis (is ,obj% ,x! ,test ,key))) + ((listp ,seq%) + (loop for ,x! in ,seq% + thereis (is ,obj% ,x! ,test ,key))))))) diff --git a/on.lisp b/on.lisp index b8fd97d..3a52fa5 100644 --- a/on.lisp +++ b/on.lisp @@ -53,3 +53,12 @@ composed together in a chain." :from-end t :initial-value (apply fn1 args)))) #'identity)) + +(defmacro with-gensyms (syms &body body) + "Binds a whole list of variables to gensyms." + `(let ,(mapcar #'(lambda (s) + `(,s (gensym))) + syms) + ,@body)) + + diff --git a/package.lisp b/package.lisp index 2b754a8..ae7e8ac 100644 --- a/package.lisp +++ b/package.lisp @@ -8,6 +8,7 @@ #:group #:flatten #:compose + #:with-gensyms ;; lol.lisp : utilities from Let Over Lambda #:defmacro! @@ -55,4 +56,5 @@ #:with-string-output-to-file #:with-read-from-file #:with-write-to-file + #:in ))