From 25f2c063b97f24dcefb5cf1d910fb8210650f252 Mon Sep 17 00:00:00 2001 From: Nicolas Petton Date: Fri, 14 Aug 2015 15:53:24 +0200 Subject: [PATCH] Use a generic function for creating streams from different sources * lisp/emacs-lisp/stream.el (stream): New generic function. * test/automated/stream-tests.el (stream-list-test): Fix a reference to the old `stream-list' function --- lisp/emacs-lisp/stream.el | 117 +++++++++++++++++---------------- test/automated/stream-tests.el | 2 +- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/lisp/emacs-lisp/stream.el b/lisp/emacs-lisp/stream.el index d5a5c9013c3..012957200b6 100644 --- a/lisp/emacs-lisp/stream.el +++ b/lisp/emacs-lisp/stream.el @@ -53,9 +53,11 @@ ;;; Code: +(eval-when-compile (require 'cl-lib)) + (eval-and-compile (defconst stream--identifier '--stream-- - "Symbol internally used to identify streams.")) + "Symbol internally used to identify streams.")) (defmacro stream--delay (&rest body) "Delay the evaluation of BODY." @@ -72,6 +74,60 @@ (defun stream--force (delayed) "Force the evaluation of DELAYED." (funcall delayed)) + + +;;; Convenient functions for creating streams + +(cl-defgeneric stream (src) + "Return a new stream from SRC.") + +(cl-defmethod stream ((seq sequence)) + "Return a stream built from the sequence SEQ. +SEQ can be a list, vector or string." + (if (seq-empty-p seq) + (stream-empty) + (stream-cons + (seq-elt seq 0) + (stream (seq-subseq seq 1))))) + +(cl-defmethod stream ((list list)) + "Return a stream built from the list LIST." + (if (null list) + (stream-empty) + (stream-cons + (car list) + (stream (cdr list))))) + +(cl-defmethod stream ((buffer buffer) &optional pos) + "Return a stream of the characters of the buffer BUFFER. +BUFFER-OR-NAME may be a buffer or a string (buffer name). +The sequence starts at POS if non-nil, 1 otherwise." + (with-current-buffer buffer + (unless pos (setq pos (point-min))) + (if (>= pos (point-max)) + (stream-empty)) + (stream-cons + (with-current-buffer buffer + (save-excursion + (save-restriction + (widen) + (goto-char pos) + (char-after (point))))) + (stream buffer (1+ pos))))) + +(defun stream-range (&optional start end step) + "Return a stream of the integers from START to END, stepping by STEP. +If START is nil, it defaults to 0. If STEP is nil, it defaults to +1. START is inclusive and END is exclusive. If END is nil, the +range is infinite." + (unless start (setq start 0)) + (unless step (setq step 1)) + (if (equal start end) + (stream-empty) + (stream-cons + start + (stream-range (+ start step) end step)))) + (defmacro stream-make (&rest body) "Return a stream built from BODY. @@ -129,8 +185,8 @@ FIRST and REST are forms and REST must return a stream." "Return a stream of the successive elements for which (PRED elt) is non-nil in STREAM." (stream-make (when (funcall pred (stream-first stream)) - (cons (stream-first stream) - (stream-take-while pred (stream-rest stream)))))) + (cons (stream-first stream) + (stream-take-while pred (stream-rest stream)))))) (defun stream-drop-while (pred stream) "Return a stream from the first element for which (PRED elt) is nil in STREAM." @@ -173,60 +229,5 @@ of FUNCTION to each element of STREAM." (cons (stream-first stream) (stream-filter pred (stream-rest stream))))))) - -;;; Convenient functions for creating streams - -(defun stream-range (&optional start end step) - "Return a stream of the integers from START to END, stepping by STEP. -If START is nil, it defaults to 0. If STEP is nil, it defaults to -1. START is inclusive and END is exclusive. If END is nil, the -range is infinite." - (unless start (setq start 0)) - (unless step (setq step 1)) - (if (equal start end) - (stream-empty) - (stream-cons - start - (stream-range (+ start step) end step)))) - -(defun stream-seq (seq) - "Return a stream built from the sequence SEQ. -SEQ can be a list, vector or string." - (cond - ((listp seq) - (stream-list seq)) - ((seq-empty-p seq) - (stream-empty)) - (t - (stream-cons - (seq-elt seq 0) - (stream-seq (seq-subseq seq 1)))))) - -(defun stream-list (list) - "Return a stream built from the list LIST." - (if (null list) - (stream-empty) - (stream-cons - (car list) - (stream-list (cdr list))))) - - -(defun stream-buffer (buffer-or-name &optional pos) - "Return a stream of the characters of the buffer BUFFER-OR-NAME. -BUFFER-OR-NAME may be a buffer or a string (buffer name). -The sequence starts at POS if non-nil, 1 otherwise." - (with-current-buffer buffer-or-name - (unless pos (setq pos (point-min))) - (if (>= pos (point-max)) - (stream-empty)) - (stream-cons - (with-current-buffer buffer-or-name - (save-excursion - (save-restriction - (widen) - (goto-char pos) - (char-after (point))))) - (stream-buffer buffer-or-name (1+ pos))))) - (provide 'stream) ;;; stream.el ends here diff --git a/test/automated/stream-tests.el b/test/automated/stream-tests.el index 59a0770301c..1693b29192d 100644 --- a/test/automated/stream-tests.el +++ b/test/automated/stream-tests.el @@ -111,7 +111,7 @@ (ert-deftest stream-list-test () (dolist (list '(nil '(1 2 3) '(a . b))) - (should (equal list (stream-to-list (stream-list list)))))) + (should (equal list (stream-to-list (stream list)))))) (provide 'stream-tests) ;;; stream-tests.el ends here -- 2.39.5