diff --git a/README.md b/README.md index 8fca125..232d6bb 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,9 @@ Functions pretending lists are trees. * [->](#--x-optional-form-rest-more) `(x &optional form &rest more)` * [->>](#--x-optional-form-rest-more) `(x &optional form &rest more)` * [-->](#---x-form-rest-more) `(x form &rest more)` +* [-some->](#-some--x-optional-form-rest-more) `(x &optional form &rest more)` +* [-some->>](#-some--x-optional-form-rest-more) `(x &optional form &rest more)` +* [-some-->](#-some---x-optional-form-rest-more) `(x &optional form &rest more)` ### Binding @@ -1776,6 +1779,39 @@ in second form, etc. (--> "def" (concat "abc" it "ghi") upcase) ;; => "ABCDEFGHI" ``` +#### -some-> `(x &optional form &rest more)` + +When expr is non-nil, thread it through the first form (via [`->`](#--x-optional-form-rest-more)), +and when that result is non-nil, through the next form, etc. + +```el +(-some-> '(2 3 5)) ;; => '(2 3 5) +(-some-> 5 square) ;; => 25 +(-some-> nil square) ;; => nil +``` + +#### -some->> `(x &optional form &rest more)` + +When expr is non-nil, thread it through the first form (via [`->>`](#--x-optional-form-rest-more)), +and when that result is non-nil, through the next form, etc. + +```el +(-some->> '(1 2 3) (-map 'square)) ;; => '(1 4 9) +(-some->> '(1 3 5) (-last 'even?) (+ 100)) ;; => nil +(-some->> '(2 4 6) (-last 'even?) (+ 100)) ;; => 106 +``` + +#### -some--> `(x &optional form &rest more)` + +When expr in non-nil, thread it through the first form (via [`-->`](#---x-form-rest-more)), +and when that result is non-nil, through the next form, etc. + +```el +(-some--> "def" (concat "abc" it "ghi")) ;; => "abcdefghi" +(-some--> nil (concat "abc" it "ghi")) ;; => nil +(-some--> '(1 3 5) (-filter 'even? it) (append it it) (-map 'square it)) ;; => nil +``` + ## Binding @@ -2449,6 +2485,7 @@ Change `readme-template.md` or `examples-to-docs.el` instead. - [Mark Oteiza](https://github.com/holomorph) contributed the script to create an info manual. - [Vasilij Schneidermann](https://github.com/wasamasa) contributed `-some`. - [William West](https://github.com/occidens) made `-fixfn` more robust at handling floats. + - [Cam Saül](https://github.com/cammsaul) contributed `-some->`, `-some->>`, and `-some-->`. Thanks! diff --git a/dash.el b/dash.el index 772a629..272aee1 100644 --- a/dash.el +++ b/dash.el @@ -1199,6 +1199,33 @@ in second form, etc." (list form x)) `(--> (--> ,x ,form) ,@more))) +(defmacro -some-> (x &optional form &rest more) + "When expr is non-nil, thread it through the first form (via `->'), +and when that result is non-nil, through the next form, etc." + (if (null form) x + (let ((result (make-symbol "result"))) + `(-some-> (-when-let (,result ,x) + (-> ,result ,form)) + ,@more)))) + +(defmacro -some->> (x &optional form &rest more) + "When expr is non-nil, thread it through the first form (via `->>'), +and when that result is non-nil, through the next form, etc." + (if (null form) x + (let ((result (make-symbol "result"))) + `(-some->> (-when-let (,result ,x) + (->> ,result ,form)) + ,@more)))) + +(defmacro -some--> (x &optional form &rest more) + "When expr in non-nil, thread it through the first form (via `-->'), +and when that result is non-nil, through the next form, etc." + (if (null form) x + (let ((result (make-symbol "result"))) + `(-some--> (-when-let (,result ,x) + (--> ,result ,form)) + ,@more)))) + (defun -grade-up (comparator list) "Grade elements of LIST using COMPARATOR relation, yielding a permutation vector such that applying this permutation to LIST diff --git a/dev/examples.el b/dev/examples.el index 56d9b5f..ef96ee1 100644 --- a/dev/examples.el +++ b/dev/examples.el @@ -733,7 +733,26 @@ new list." (defexamples --> (--> "def" (concat "abc" it "ghi")) => "abcdefghi" (--> "def" (concat "abc" it "ghi") (upcase it)) => "ABCDEFGHI" - (--> "def" (concat "abc" it "ghi") upcase) => "ABCDEFGHI")) + (--> "def" (concat "abc" it "ghi") upcase) => "ABCDEFGHI") + + (defexamples -some-> + (-some-> '(2 3 5)) => '(2 3 5) + (-some-> 5 square) => 25 + (-some-> nil square) => nil + (-some-> 5 even? square) => nil) + + (defexamples -some->> + (-some->> '(1 2 3) (-map 'square)) => '(1 4 9) + (-some->> '(1 3 5) (-last 'even?) (+ 100)) => nil + (-some->> '(2 4 6) (-last 'even?) (+ 100)) => 106 + (-some->> '("A" "B" :c) (-filter 'stringp) (-reduce 'concat)) => "AB" + (-some->> '(:a :b :c) (-filter 'stringp) (-reduce 'concat)) => nil) + + (defexamples -some--> + (-some--> "def" (concat "abc" it "ghi")) => "abcdefghi" + (-some--> nil (concat "abc" it "ghi")) => nil + (-some--> '(1 3 5) (-filter 'even? it) (append it it) (-map 'square it)) => nil + (-some--> '(2 4 6) (-filter 'even? it) (append it it) (-map 'square it)) => '(4 16 36 4 16 36))) (def-example-group "Binding" "Convenient versions of `let` and `let*` constructs combined with flow control."