From 93e9009c827bc5b0f67c683a4e1748c90c6e4686 Mon Sep 17 00:00:00 2001 From: Michael Heerdegen Date: Mon, 18 Dec 2017 12:49:38 +0100 Subject: [PATCH] Implement `seq-mapn' method for streams * stream/stream.el (seq-mapn): New method. * stream/tests/stream-tests.el (stream-seq-mapn-test): New test. And add a `deftest-for-delayed-evaluation'. --- packages/stream/stream.el | 22 ++++++++++++++++++++++ packages/stream/tests/stream-tests.el | 15 +++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/packages/stream/stream.el b/packages/stream/stream.el index b412807e2..3f6bc4b5b 100644 --- a/packages/stream/stream.el +++ b/packages/stream/stream.el @@ -321,6 +321,28 @@ applications of FUNCTION on each element of STREAM in succession." (cons (funcall function (stream-first stream)) (seq-map function (stream-rest stream)))))) +(cl-defmethod seq-mapn (function (stream stream) &rest streams) + "Map FUNCTION over the STREAMS. + +Example: this prints the first ten Fibonacci numbers: + + (letrec ((fibs (stream-cons + 1 + (stream-cons + 1 + (seq-mapn #'+ fibs (stream-rest fibs)))))) + (seq-do #'print (seq-take fibs 10))) + +\(fn FUNCTION STREAMS...)" + (if (not (seq-every-p #'streamp streams)) + (cl-call-next-method) + (cl-labels ((do-mapn (f streams) + (stream-make + (unless (seq-some #'stream-empty-p streams) + (cons (apply f (mapcar #'stream-first streams)) + (do-mapn f (mapcar #'stream-rest streams))))))) + (do-mapn function (cons stream streams))))) + (cl-defmethod seq-do (function (stream stream)) "Evaluate FUNCTION for each element of STREAM eagerly, and return nil. diff --git a/packages/stream/tests/stream-tests.el b/packages/stream/tests/stream-tests.el index decf3ad47..896c72993 100644 --- a/packages/stream/tests/stream-tests.el +++ b/packages/stream/tests/stream-tests.el @@ -166,6 +166,18 @@ (should (= -1 (stream-first (seq-map #'- (stream-range 1))))) (should (= -2 (stream-first (stream-rest (seq-map #'- (stream-range 1))))))) +(ert-deftest stream-seq-mapn-test () + (should (streamp (seq-mapn #'+ (stream (list 1 2 3)) (stream (list 4 5 6))))) + (should (not (streamp (seq-mapn #'+ (stream (list 1 2 3)) (stream (list 4 5 6)) (list 7 8 9))))) + (should (= 2 (seq-length (seq-mapn #'+ (stream (list 1 2 3)) (stream (list 4 5)))))) + (should (equal (letrec ((fibs (stream-cons + 1 + (stream-cons + 1 + (seq-mapn #'+ fibs (stream-rest fibs)))))) + (seq-into (seq-take fibs 10) 'list)) + '(1 1 2 3 5 8 13 21 34 55)))) + (ert-deftest stream-seq-do-test () (let ((result '())) (seq-do @@ -292,6 +304,9 @@ (deftest-for-delayed-evaluation (seq-drop (make-delayed-test-stream) 2)) (deftest-for-delayed-evaluation (seq-take-while #'numberp (make-delayed-test-stream))) (deftest-for-delayed-evaluation (seq-map #'identity (make-delayed-test-stream))) +(deftest-for-delayed-evaluation (seq-mapn #'cons + (make-delayed-test-stream) + (make-delayed-test-stream))) (deftest-for-delayed-evaluation (seq-filter #'cl-evenp (make-delayed-test-stream))) (deftest-for-delayed-evaluation (stream-delay (make-delayed-test-stream))) (deftest-for-delayed-evaluation (seq-copy (make-delayed-test-stream))) -- 2.15.1