`take-while` and `drop-while`
author |
Steve Losh <steve@stevelosh.com> |
date |
Wed, 01 Mar 2017 19:14:51 +0000 |
parents |
2746fc7667d9
|
children |
c49425b33f17
|
branches/tags |
(none) |
files |
DOCUMENTATION.markdown losh.lisp package.lisp |
Changes
--- a/DOCUMENTATION.markdown Mon Feb 27 13:52:44 2017 +0000
+++ b/DOCUMENTATION.markdown Wed Mar 01 19:14:51 2017 +0000
@@ -306,7 +306,7 @@
&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
@@ -335,6 +335,42 @@
+### `GATHERING-VECTOR` (macro)
+
+ (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)
+
+
+
### `IF-FOUND` (macro)
(IF-FOUND VAR LOOKUP-EXPR THEN ELSE)
@@ -608,6 +644,14 @@
+### `PROFILE` (macro)
+
+ (PROFILE
+ &BODY
+ BODY)
+
+Profile `body` and dump the report to `lisp.prof`.
+
### `SHUT-UP` (macro)
(SHUT-UP
@@ -1463,6 +1507,24 @@
+### `DROP-WHILE` (function)
+
+ (DROP-WHILE PREDICATE SEQ)
+
+Drop elements from `seq` as long as `predicate` remains true.
+
+ The result will be a fresh sequence of the same type as `seq`.
+
+ Example:
+
+ (drop-while #'evenp '(2 4 5 6 7 8))
+ ; => (5 6 7 8)
+
+ (drop-while #'evenp #(2))
+ ; => #(2)
+
+
+
### `ENUMERATE` (function)
(ENUMERATE SEQUENCE &KEY (START 0) (STEP 1) KEY)
@@ -1609,6 +1671,24 @@
+### `TAKE-WHILE` (function)
+
+ (TAKE-WHILE PREDICATE SEQ)
+
+Take elements from `seq` as long as `predicate` remains true.
+
+ The result will be a fresh sequence of the same type as `seq`.
+
+ Example:
+
+ (take-while #'evenp '(2 4 5 6 7 8))
+ ; => (2 4)
+
+ (take-while #'evenp #(1))
+ ; => #()
+
+
+
## Package `LOSH.WEIGHTLISTS`
A simple data structure for choosing random items with weighted probabilities.
--- a/losh.lisp Mon Feb 27 13:52:44 2017 +0000
+++ b/losh.lisp Wed Mar 01 19:14:51 2017 +0000
@@ -1727,6 +1727,33 @@
(sequence (take-seq n seq))))
+(defun-inline take-while-list (predicate list)
+ (iterate (for item :in list)
+ (while (funcall predicate item))
+ (collect item)))
+
+(defun-inline take-while-seq (predicate seq)
+ (subseq seq 0 (position-if-not predicate seq)))
+
+(defun take-while (predicate seq)
+ "Take elements from `seq` as long as `predicate` remains true.
+
+ The result will be a fresh sequence of the same type as `seq`.
+
+ Example:
+
+ (take-while #'evenp '(2 4 5 6 7 8))
+ ; => (2 4)
+
+ (take-while #'evenp #(1))
+ ; => #()
+
+ "
+ (ctypecase seq
+ (list (take-while-list predicate seq))
+ (sequence (take-while-seq predicate seq))))
+
+
(defun-inline drop-list (n list)
(copy-list (nthcdr n list)))
@@ -1757,6 +1784,36 @@
(sequence (drop-seq n seq))))
+(defun-inline drop-while-list (predicate list)
+ (iterate (for tail :on list)
+ (while (funcall predicate (first tail)))
+ (finally (return (copy-list tail)))))
+
+(defun-inline drop-while-seq (predicate seq)
+ (let ((start (position-if-not predicate seq)))
+ (if start
+ (subseq seq start)
+ (subseq seq 0 0))))
+
+(defun drop-while (predicate seq)
+ "Drop elements from `seq` as long as `predicate` remains true.
+
+ The result will be a fresh sequence of the same type as `seq`.
+
+ Example:
+
+ (drop-while #'evenp '(2 4 5 6 7 8))
+ ; => (5 6 7 8)
+
+ (drop-while #'evenp #(2))
+ ; => #(2)
+
+ "
+ (ctypecase seq
+ (list (drop-while-list predicate seq))
+ (sequence (drop-while-seq predicate seq))))
+
+
(defun extrema (predicate sequence)
"Return the smallest and largest elements of `sequence` according to `predicate`.
--- a/package.lisp Mon Feb 27 13:52:44 2017 +0000
+++ b/package.lisp Wed Mar 01 19:14:51 2017 +0000
@@ -268,7 +268,9 @@
:proportions
:group-by
:take
- :drop))
+ :take-while
+ :drop
+ :drop-while))
(defpackage :losh.weightlists
(:documentation