From 999cae96f0c83b068aefff73afa61fe9e7dfa536 Mon Sep 17 00:00:00 2001 From: "Basil L. Contovounesios" Date: Sat, 16 Jan 2021 00:10:37 +0000 Subject: [PATCH] Fix short-circuiting of --first * dash.el (--first): Stop looping even if needle is nil. Extend docstring. (-first): Extend docstring. * dev/examples.el (-first): Extend tests. * README.md: * dash.texi: Regenerate docs. --- README.md | 14 +++++++------- dash.el | 18 +++++++++++------- dash.texi | 18 +++++++++--------- dev/examples.el | 29 ++++++++++++++++++++++++----- 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index ff51a38..d019838 100644 --- a/README.md +++ b/README.md @@ -1964,16 +1964,16 @@ See also: [`-flatten-n`](#-flatten-n-num-list), [`-table`](#-table-fn-rest-lists #### -first `(pred list)` -Return the first x in `list` where (`pred` x) is non-nil, else nil. - +Return the first item in `list` for which `pred` returns non-nil. +Return nil if no such element is found. To get the first item in the list no questions asked, use `car`. - -Alias: `-find` +Alias: `-find`. +This function's anaphoric counterpart is `--first`. ```el -(-first 'even? '(1 2 3)) ;; => 2 -(-first 'even? '(1 3 5)) ;; => nil -(-first 'null '(1 3 5)) ;; => nil +(-first #'natnump '(-1 0 1)) ;; => 0 +(-first #'null '(1 2 3)) ;; => nil +(--first (> it 2) '(1 2 3)) ;; => 3 ``` #### -some `(pred list)` diff --git a/dash.el b/dash.el index 3c51812..c8b652b 100644 --- a/dash.el +++ b/dash.el @@ -741,20 +741,24 @@ If ELEMENTS is non nil, append these to the list as well." (-concat list (list elem) elements)) (defmacro --first (form list) - "Anaphoric form of `-first'." + "Return the first item in LIST for which FORM evals to non-nil. +Return nil if no such element is found. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-first'." (declare (debug (form form))) (let ((n (make-symbol "needle"))) `(let (,n) - (--each-while ,list (not ,n) - (when ,form (setq ,n it))) + (--each-while ,list (or (not ,form) + (ignore (setq ,n it)))) ,n))) (defun -first (pred list) - "Return the first x in LIST where (PRED x) is non-nil, else nil. - + "Return the first item in LIST for which PRED returns non-nil. +Return nil if no such element is found. To get the first item in the list no questions asked, use `car'. - -Alias: `-find'" +Alias: `-find'. +This function's anaphoric counterpart is `--first'." (--first (funcall pred it) list)) (defalias '-find '-first) diff --git a/dash.texi b/dash.texi index a98d7df..e998024 100644 --- a/dash.texi +++ b/dash.texi @@ -2973,24 +2973,24 @@ See also: @code{-flatten-n} (@pxref{-flatten-n}), @code{-table} (@pxref{-table}) @anchor{-first} @defun -first (pred list) -Return the first x in @var{list} where (@var{pred} x) is non-nil, else nil. - +Return the first item in @var{list} for which @var{pred} returns non-nil. +Return nil if no such element is found. To get the first item in the list no questions asked, use @code{car}. - -Alias: @code{-find} +Alias: @code{-find}. +This function's anaphoric counterpart is @code{--first}. @example @group -(-first 'even? '(1 2 3)) - @result{} 2 +(-first #'natnump '(-1 0 1)) + @result{} 0 @end group @group -(-first 'even? '(1 3 5)) +(-first #'null '(1 2 3)) @result{} nil @end group @group -(-first 'null '(1 3 5)) - @result{} nil +(--first (> it 2) '(1 2 3)) + @result{} 3 @end group @end example @end defun diff --git a/dev/examples.el b/dev/examples.el index 30e55c3..18e5668 100644 --- a/dev/examples.el +++ b/dev/examples.el @@ -980,11 +980,30 @@ value rather than consuming a list to produce a single value." (-flatten-n 2 (apply '-table 'list (-repeat 3 '(1 2)))) => '((1 1 1) (2 1 1) (1 2 1) (2 2 1) (1 1 2) (2 1 2) (1 2 2) (2 2 2))) (defexamples -first - (-first 'even? '(1 2 3)) => 2 - (-first 'even? '(1 3 5)) => nil - (-first 'null '(1 3 5)) => nil - (-first 'null '(1 3 ())) => nil - (--first (> it 2) '(1 2 3)) => 3) + (-first #'natnump '(-1 0 1)) => 0 + (-first #'null '(1 2 3)) => nil + (--first (> it 2) '(1 2 3)) => 3 + (let ((c 0)) (--first (setq c (1+ c)) '(nil nil nil)) c) => 1 + (--first nil '(1 2 3)) => nil + (--first nil '(1)) => nil + (--first nil '()) => nil + (-first #'ignore '(1 2 3)) => nil + (-first #'ignore '(1)) => nil + (-first #'ignore '()) => nil + (--first (not it) '(1 2 nil)) => nil + (--first (not it) '(nil 1 2)) => nil + (--first (not it) '(nil)) => nil + (--first (not it) '()) => nil + (-first #'null '(1 2 nil)) => nil + (-first #'null '(nil 1 2)) => nil + (-first #'null '(nil)) => nil + (-first #'null '()) => nil + (--first t '(1 2 3)) => 1 + (--first t '(1)) => 1 + (--first t '()) => nil + (-first #'identity '(1 2 3)) => 1 + (-first #'identity '(1)) => 1 + (-first #'identity '()) => nil) (defexamples -some (-some 'even? '(1 2 3)) => t