From: Michael Heerdegen Date: Thu, 2 Jun 2016 00:42:43 +0000 (+0200) Subject: Add some more basic stream operations X-Git-Url: https://code.delx.au/gnu-emacs-elpa/commitdiff_plain/8b3326ff7251ba402002dfcbb9272f59547f09ab Add some more basic stream operations --- diff --git a/packages/stream/stream.el b/packages/stream/stream.el index 22cecac25..62eb3b6a5 100644 --- a/packages/stream/stream.el +++ b/packages/stream/stream.el @@ -333,6 +333,51 @@ calling this function." (cl-defmethod seq-copy ((stream stream)) "Return a shallow copy of STREAM." (stream-delay stream)) + + +;;; More stream operations + +(defun stream-scan (function init stream) + "Return a stream of successive reduced values for STREAM. + +If the elements of a stream s are s_1, s_2, ..., the elements +S_1, S_2, ... of the stream returned by \(stream-scan f init s\) +are defined recursively by + + S_1 = init + S_(n+1) = (funcall f S_n s_n) + +as long as s_n exists. + +Example: + + (stream-scan #'* 1 (stream-range 1)) + +returns a stream of the factorials." + (let ((res init)) + (stream-cons + res + (seq-map (lambda (el) (setq res (funcall function res el))) + stream)))) + +(defun stream-flush (stream) + "Request all elements from STREAM in order for side effects only." + (while (not (stream-empty-p stream)) + (cl-callf stream-rest stream))) + +(defun stream-iterate-function (function value) + "Return a stream of repeated applications of FUNCTION to VALUE. +The returned stream starts with VALUE. Any successive element +will be found by calling FUNCTION on the preceding element." + (stream-cons + value + (stream-iterate-function function (funcall function value)))) + +(defun stream-concatenate (stream-of-streams) + "Concatenate all streams in STREAM-OF-STREAMS and return the result. +All elements in STREAM-OF-STREAMS must be streams. The result is +a stream." + (seq-reduce #'stream-append stream-of-streams (stream-empty))) (defun stream-of-directory-files-1 (directory &optional nosort recurse follow-links) "Helper for `stream-of-directory-files'." diff --git a/packages/stream/tests/stream-tests.el b/packages/stream/tests/stream-tests.el index 23a54b5ec..16b5756ea 100644 --- a/packages/stream/tests/stream-tests.el +++ b/packages/stream/tests/stream-tests.el @@ -242,5 +242,28 @@ (should (= 2 (stream-first str))) (should (null (stream-pop stream-empty))))) +(ert-deftest stream-scan-test () + (should (eq (seq-elt (stream-scan #'* 1 (stream-range 1)) 4) 24))) + +(ert-deftest stream-flush-test () + (should (let* ((times 0) + (count (lambda () (cl-incf times)))) + (letrec ((make-test-stream (lambda () (stream-cons (progn (funcall count) nil) + (funcall make-test-stream))))) + (stream-flush (seq-take (funcall make-test-stream) 5)) + (eq times 5))))) + +(ert-deftest stream-iterate-function-test () + (should (equal (list 0 1 2) (seq-into-sequence (seq-take (stream-iterate-function #'1+ 0) 3))))) + +(ert-deftest stream-concatenate-test () + (should (equal (seq-into-sequence + (stream-concatenate + (stream (list (stream (list 1 2 3)) + (stream (list)) + (stream (list 4)) + (stream (list 5 6 7 8 9)))))) + (list 1 2 3 4 5 6 7 8 9)))) + (provide 'stream-tests) ;;; stream-tests.el ends here