+ (stream-delay stream))
+\f
+
+;;; 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'."
+ (stream-delay
+ (if (file-accessible-directory-p directory)
+ (let (files dirs (reverse-fun (if nosort #'identity #'nreverse)))
+ (dolist (file (directory-files directory t nil nosort))
+ (let ((is-dir (file-directory-p file)))
+ (unless (and is-dir
+ (member (file-name-nondirectory (directory-file-name file))
+ '("." "..")))
+ (push file files)
+ (when (and is-dir
+ (or follow-links (not (file-symlink-p file)))
+ (if (functionp recurse) (funcall recurse file) recurse))
+ (push file dirs)))))
+ (apply #'stream-append
+ (stream (funcall reverse-fun files))
+ (mapcar
+ (lambda (dir) (stream-of-directory-files-1 dir nosort recurse follow-links))
+ (funcall reverse-fun dirs))))
+ (stream-empty))))
+
+(defun stream-of-directory-files (directory &optional full nosort recurse follow-links filter)
+ "Return a stream of names of files in DIRECTORY.
+Call `directory-files' to list file names in DIRECTORY and make
+the result a stream. Don't include files named \".\" or \"..\".
+The arguments FULL and NOSORT are directly passed to
+`directory-files'.
+
+Third optional argument RECURSE non-nil means recurse on
+subdirectories. If RECURSE is a function, it should be a
+predicate accepting one argument, an absolute file name of a
+directory, and return non-nil when the returned stream should
+recurse into that directory. Any other non-nil value means
+recurse into every readable subdirectory.
+
+Even with recurse non-nil, don't descent into directories by
+following symlinks unless FOLLOW-LINKS is non-nil.
+
+If FILTER is non-nil, it should be a predicate accepting one
+argument, an absolute file name. It is used to limit the
+resulting stream to the files fulfilling this predicate."
+ (let* ((stream (stream-of-directory-files-1 directory nosort recurse follow-links))
+ (filtered-stream (if filter (seq-filter filter stream) stream)))
+ (if full filtered-stream
+ (seq-map (lambda (file) (file-relative-name file directory)) filtered-stream))))