diff --git a/README.md b/README.md index 448c548..2daa608 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ This is so much a work in progress that you should definitely not be using it ye * [!reduce](#reduce-fn-list) `(fn list)` * [!filter](#filter-fn-list) `(fn list)` * [!remove](#remove-fn-list) `(fn list)` +* [!keep](#keep-fn-list) `(fn list)` * [!concat](#concat-rest-lists) `(&rest lists)` * [!mapcat](#mapcat-fn-list) `(fn list)` * [!partial](#partial-fn-rest-args) `(fn &rest args)` @@ -113,6 +114,16 @@ Returns a new list of the items in `list` for which `fn` returns nil. (!!remove (= 0 (% it 2)) '(1 2 3 4)) ;; => '(1 3) ``` +### !keep `(fn list)` + +Returns a new list of the non-nil results of applying `fn` to the items in `list`. + +```cl +(!keep 'cdr '((1 2 3) (4 5) (6))) ;; => '((2 3) (5)) +(!keep (lambda (num) (when (> num 3) (* 10 num))) '(1 2 3 4 5 6)) ;; => '(40 50 60) +(!!keep (when (> it 3) (* 10 it)) '(1 2 3 4 5 6)) ;; => '(40 50 60) +``` + ### !concat `(&rest lists)` Returns a new list with the concatenation of the elements in diff --git a/bang.el b/bang.el index 3022d28..eb23382 100644 --- a/bang.el +++ b/bang.el @@ -96,6 +96,22 @@ exposed as `acc`." "Returns a new list of the items in LIST for which FN returns nil." (!!remove (funcall fn it) list)) +(defmacro !!keep (form list) + "Anaphoric form of `!keep'." + `(let ((!--list ,list) + (!--result '())) + (while !--list + (let* ((it (car !--list)) + (mapped ,form)) + (when mapped + (setq !--result (cons mapped !--result)))) + (setq !--list (cdr !--list))) + (nreverse !--result))) + +(defun !keep (fn list) + "Returns a new list of the non-nil results of applying FN to the items in LIST." + (!!keep (funcall fn it) list)) + (defun !concat (&rest lists) "Returns a new list with the concatenation of the elements in the supplied LISTS." diff --git a/examples.el b/examples.el index 79c23c3..3c4607f 100644 --- a/examples.el +++ b/examples.el @@ -40,6 +40,11 @@ (let ((mod 2)) (!remove (lambda (num) (= 0 (% num mod))) '(1 2 3 4))) => '(1 3) (let ((mod 2)) (!!remove (= 0 (% it mod)) '(1 2 3 4))) => '(1 3)) +(defexamples !keep + (!keep 'cdr '((1 2 3) (4 5) (6))) => '((2 3) (5)) + (!keep (lambda (num) (when (> num 3) (* 10 num))) '(1 2 3 4 5 6)) => '(40 50 60) + (!!keep (when (> it 3) (* 10 it)) '(1 2 3 4 5 6)) => '(40 50 60)) + (defexamples !concat (!concat '(1)) => '(1) (!concat '(1) '(2)) => '(1 2)