# HG changeset patch # User Steve Losh # Date 1488203564 0 # Node ID 2746fc7667d9e49f74bc7752fa5c8d47955c42f6 # Parent 85823854b8cbdb3ec8eaf248aeb7b1bd2acafe01 Add `gathering-vector` diff -r 85823854b8cb -r 2746fc7667d9 losh.lisp --- a/losh.lisp Wed Feb 22 11:19:29 2017 +0000 +++ b/losh.lisp Mon Feb 27 13:52:44 2017 +0000 @@ -480,7 +480,7 @@ ,else)))) (defmacro gathering (&body body) - "Run `body` to gather some things and return them. + "Run `body` to gather some things and return a fresh list of them. `body` will be executed with the symbol `gather` bound to a function of one argument. Once `body` has finished, a list of everything `gather` was called @@ -516,6 +516,46 @@ ,@body) (queue-contents ,result)))) +(defmacro gathering-vector (options &body body) + "Run `body` to gather some things and return a fresh vector of them. + + `body` will be executed with the symbol `gather` bound to a function of one + argument. Once `body` has finished, a vector of everything `gather` was + called on will be returned. This vector will be adjustable and have a fill + pointer. + + It's handy for pulling results out of code that executes procedurally and + doesn't return anything, like `maphash` or Alexandria's `map-permutations`. + + The `gather` function can be passed to other functions, but should not be + retained once the `gathering` form has returned (it would be useless to do so + anyway). + + Examples: + + (gathering-vector () + (dotimes (i 5) + (gather i)) + => + #(0 1 2 3 4) + + (gathering-vector () + (mapc #'gather '(1 2 3)) + (mapc #'gather '(a b))) + => + #(1 2 3 a b) + + " + (destructuring-bind (&key (size 16)) + options + (with-gensyms (result) + `(let ((,result (make-array ,size :adjustable t :fill-pointer 0))) + (flet ((gather (item) + (vector-push-extend item ,result))) + (declare (dynamic-extent #'gather)) + ,@body) + ,result)))) + (defmacro when-let* (binding-forms &body body) "Bind the forms in `binding-forms` in order, short-circuiting on `nil`. diff -r 85823854b8cb -r 2746fc7667d9 package.lisp --- a/package.lisp Wed Feb 22 11:19:29 2017 +0000 +++ b/package.lisp Mon Feb 27 13:52:44 2017 +0000 @@ -61,6 +61,7 @@ :when-found :if-found :gathering + :gathering-vector :gather :when-let* :multiple-value-bind*))