diff --git a/README.md b/README.md index 1c309e5..15725a3 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Or you can just dump `dash.el` in your load path somewhere. * [-all?](#-all-fn-list) `(fn list)` * [-none?](#-none-fn-list) `(fn list)` * [-each](#-each-list-fn) `(list fn)` +* [-each-while](#-each-while-list-pred-fn) `(list pred fn)` * [-take](#-take-n-list) `(n list)` * [-drop](#-drop-n-list) `(n list)` * [-take-while](#-take-while-fn-list) `(fn list)` @@ -227,6 +228,16 @@ Calls `fn` with every item in `list`. Returns nil, used for side-effects only. (let (s) (--each '(1 2 3) (setq s (cons it s))) s) ;; => '(3 2 1) ``` +### -each-while `(list pred fn)` + +Calls `fn` with every item in `list` while (`pred` item) is non-nil. +Returns nil, used for side-effects only. + +```cl +(let (s) (-each-while '(2 4 5 6) 'even? (lambda (item) (!cons item s))) s) ;; => '(4 2) +(let (s) (--each-while '(1 2 3 4) (< it 3) (!cons it s)) s) ;; => '(2 1) +``` + ### -take `(n list)` Returns a new list of the first `n` items in `list`, or all items if there are fewer than `n`. diff --git a/dash.el b/dash.el index d7ed7f1..3c38370 100644 --- a/dash.el +++ b/dash.el @@ -48,6 +48,22 @@ "Calls FN with every item in LIST. Returns nil, used for side-effects only." (--each list (funcall fn it))) +(defmacro --each-while (list pred form) + "Anaphoric form of `-each-while'." + (let ((l (make-symbol "list")) + (c (make-symbol "continue"))) + `(let ((,l ,list) + (,c t)) + (while (and ,l ,c) + (let ((it (car ,l))) + (if ,pred ,form (setq ,c nil))) + (!cdr ,l))))) + +(defun -each-while (list pred fn) + "Calls FN with every item in LIST while (PRED item) is non-nil. +Returns nil, used for side-effects only." + (--each-while list (funcall pred it) (funcall fn it))) + (defun -map (fn list) "Returns a new list consisting of the result of applying FN to the items in LIST." (mapcar fn list)) diff --git a/examples.el b/examples.el index bbe5654..a0aca3a 100644 --- a/examples.el +++ b/examples.el @@ -83,6 +83,10 @@ (let (s) (--each '(1 2 3) (setq s (cons it s))) s) => '(3 2 1) (let (s) (--each (reverse (three-letters)) (setq s (cons it s))) s) => '("A" "B" "C")) +(defexamples -each-while + (let (s) (-each-while '(2 4 5 6) 'even? (lambda (item) (!cons item s))) s) => '(4 2) + (let (s) (--each-while '(1 2 3 4) (< it 3) (!cons it s)) s) => '(2 1)) + (defexamples -take (-take 3 '(1 2 3 4 5)) => '(1 2 3) (-take 17 '(1 2 3 4 5)) => '(1 2 3 4 5))