diff --git a/README.md b/README.md index eef76a9..951e5bc 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ Or you can just dump `dash.el` in your load path somewhere. * [-group-by](#-group-by-fn-list) `(fn list)` * [-interpose](#-interpose-sep-list) `(sep list)` * [-interleave](#-interleave-rest-lists) `(&rest lists)` +* [-zip-with](#-zip-with-fn-list1-list2) `(fn list1 list2)` +* [-zip](#-zip-list1-list2) `(list1 list2)` * [-first](#-first-pred-list) `(pred list)` * [-union](#-union-list-list2) `(list list2)` * [-difference](#-difference-list-list2) `(list list2)` @@ -447,6 +449,32 @@ Returns a new list of the first item in each list, then the second etc. (-interleave '(1 2 3) '("a" "b")) ;; => '(1 "a" 2 "b") ``` +### -zip-with `(fn list1 list2)` + +Zip the two lists `list1` and `list2` using a function `fn`. This +function is applied pairwise taking as first argument element of +`list1` and as second argument element of `list2` at corresponding +position. + +```cl +(-zip-with '+ '(1 2 3) '(4 5 6)) ;; => '(5 7 9) +(-zip-with 'cons '(1 2 3) '(4 5 6)) ;; => '((1 . 4) (2 . 5) (3 . 6)) +(--zip-with (concat it " and " other) '("Batman" "Jekyll") '("Robin" "Hyde")) ;; => '("Batman and Robin" "Jekyll and Hyde") +``` + +### -zip `(list1 list2)` + +Zip the two lists together. Return the list where elements +are cons pairs with car being element from `list1` and cdr being +element from `list2`. The length of the returned list is the +length of the shorter one. + +```cl +(-zip '(1 2 3) '(4 5 6)) ;; => '((1 . 4) (2 . 5) (3 . 6)) +(-zip '(1 2 3) '(4 5 6 7)) ;; => '((1 . 4) (2 . 5) (3 . 6)) +(-zip '(1 2 3 4) '(4 5 6)) ;; => '((1 . 4) (2 . 5) (3 . 6)) +``` + ### -first `(pred list)` Returns the first x in `list` where (`pred` x) is non-nil, else nil. @@ -642,7 +670,7 @@ Change `readme-template.md` or `examples-to-docs.el` instead. ## Contributors - - [Fuco](https://github.com/Fuco1) contributed `-union` and `-separate`. + - [Matus Goljer](https://github.com/Fuco1) contributed `-union`, `-separate`, `-zip` and `-zip-with`. - [Takafumi Arakaki](https://github.com/tkf) contributed `-group-by`. - [tali713](https://github.com/tali713) is the author of `-applify`. - [Víctor M. Valenzuela](https://github.com/vemv) contributed `-repeat`. diff --git a/dash.el b/dash.el index aa5358e..b9ae7d6 100644 --- a/dash.el +++ b/dash.el @@ -490,6 +490,46 @@ elements of LIST. Keys are compared by `equal'." (setq lists (-map 'cdr lists))) (nreverse result))) +(defmacro --separate (form list) + "Anaphoric form of `-separate'." + (let ((y (make-symbol "yes")) + (n (make-symbol "no"))) + `(let (,y ,n) + (--each ,list (if ,form (!cons it ,y) (!cons it ,n))) + (list (nreverse ,y) (nreverse ,n))))) + +(defmacro --zip-with (form list1 list2) + "Anaphoric form of `-zip-with'. + +The elements in list1 is bound as `it`, the elements in list2 as `other`." + (let ((r (make-symbol "result")) + (l1 (make-symbol "list1")) + (l2 (make-symbol "list2"))) + `(let ((,r nil) + (,l1 ,list1) + (,l2 ,list2)) + (while (and ,l1 ,l2) + (let ((it (car ,l1)) + (other (car ,l2))) + (!cons ,form ,r) + (!cdr ,l1) + (!cdr ,l2))) + (nreverse ,r)))) + +(defun -zip-with (fn list1 list2) + "Zip the two lists LIST1 and LIST2 using a function FN. This +function is applied pairwise taking as first argument element of +LIST1 and as second argument element of LIST2 at corresponding +position." + (--zip-with (funcall fn it other) list1 list2)) + +(defun -zip (list1 list2) + "Zip the two lists together. Return the list where elements +are cons pairs with car being element from LIST1 and cdr being +element from LIST2. The length of the returned list is the +length of the shorter one." + (-zip-with 'cons list1 list2)) + (defun -partial (fn &rest args) "Takes a function FN and fewer than the normal arguments to FN, and returns a fn that takes a variable number of additional ARGS. @@ -682,6 +722,9 @@ Returns nil if N is less than 1." "-partition-all" "-interpose" "-interleave" + "--zip-with" + "-zip-with" + "-zip" "--map-when" "-map-when" "--replace-where" @@ -703,6 +746,7 @@ Returns nil if N is less than 1." "it" "it-index" "acc" + "other" ))) (font-lock-add-keywords 'emacs-lisp-mode `((,(concat "\\<" (regexp-opt special-variables 'paren) "\\>") 1 font-lock-variable-name-face)) 'append) diff --git a/dev/examples.el b/dev/examples.el index d02c5a5..f18a77a 100644 --- a/dev/examples.el +++ b/dev/examples.el @@ -181,6 +181,16 @@ (-interleave '(1 2 3) '("a" "b")) => '(1 "a" 2 "b") (-interleave '(1 2 3) '("a" "b" "c" "d")) => '(1 "a" 2 "b" 3 "c")) +(defexamples -zip-with + (-zip-with '+ '(1 2 3) '(4 5 6)) => '(5 7 9) + (-zip-with 'cons '(1 2 3) '(4 5 6)) => '((1 . 4) (2 . 5) (3 . 6)) + (--zip-with (concat it " and " other) '("Batman" "Jekyll") '("Robin" "Hyde")) => '("Batman and Robin" "Jekyll and Hyde")) + +(defexamples -zip + (-zip '(1 2 3) '(4 5 6)) => '((1 . 4) (2 . 5) (3 . 6)) + (-zip '(1 2 3) '(4 5 6 7)) => '((1 . 4) (2 . 5) (3 . 6)) + (-zip '(1 2 3 4) '(4 5 6)) => '((1 . 4) (2 . 5) (3 . 6))) + (defexamples -first (-first 'even? '(1 2 3)) => 2 (-first 'even? '(1 3 5)) => nil diff --git a/readme-template.md b/readme-template.md index e56c4bf..6a60fb7 100644 --- a/readme-template.md +++ b/readme-template.md @@ -71,7 +71,7 @@ Change `readme-template.md` or `examples-to-docs.el` instead. ## Contributors - - [Fuco](https://github.com/Fuco1) contributed `-union` and `-separate`. + - [Matus Goljer](https://github.com/Fuco1) contributed `-union`, `-separate`, `-zip` and `-zip-with`. - [Takafumi Arakaki](https://github.com/tkf) contributed `-group-by`. - [tali713](https://github.com/tali713) is the author of `-applify`. - [Víctor M. Valenzuela](https://github.com/vemv) contributed `-repeat`.