From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Michael Heerdegen Newsgroups: gmane.emacs.devel Subject: Re: [PATCH] Gnu Elpa: stream.el: Add some more basic stream operations Date: Thu, 02 Jun 2016 17:50:39 +0200 Message-ID: <87porzmvxs.fsf@web.de> References: <87twhbmwbx.fsf@web.de> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1464885459 19756 80.91.229.3 (2 Jun 2016 16:37:39 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 2 Jun 2016 16:37:39 +0000 (UTC) Cc: Nicolas Petton To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Jun 02 18:37:30 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1b8Vcf-0003XR-72 for ged-emacs-devel@m.gmane.org; Thu, 02 Jun 2016 18:37:29 +0200 Original-Received: from localhost ([::1]:48761 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b8Vce-0004sQ-DM for ged-emacs-devel@m.gmane.org; Thu, 02 Jun 2016 12:37:28 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:43780) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b8UtW-0004s6-QH for emacs-devel@gnu.org; Thu, 02 Jun 2016 11:50:52 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b8UtQ-0001gu-Qn for emacs-devel@gnu.org; Thu, 02 Jun 2016 11:50:49 -0400 Original-Received: from mout.web.de ([212.227.15.14]:49639) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b8UtQ-0001gF-Eq for emacs-devel@gnu.org; Thu, 02 Jun 2016 11:50:44 -0400 Original-Received: from drachen.dragon ([94.217.122.112]) by smtp.web.de (mrweb002) with ESMTPSA (Nemesis) id 0MdLYB-1arehH2gB1-00IUE2; Thu, 02 Jun 2016 17:50:40 +0200 In-Reply-To: <87twhbmwbx.fsf@web.de> (Michael Heerdegen's message of "Thu, 02 Jun 2016 17:42:10 +0200") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.94 (gnu/linux) X-Provags-ID: V03:K0:BwQUGRMZEWih2bwYbp3cwOgEX4QvqdCpmJYNFvLeGiTa+5gWudt lYRpar1CLKRVspGNgtdZISIHGMZ7fflO6oeiWfiKozrHomxBekli9GNrYiKCWxUf+GFUNkH 2APL3sdtuSc3Eeqgjsl3qy441ClzJQw8jcWCtFt0sjkjygVQE0GTO6rt1TPh9hP0QL+B/Bp gIImU3QNM5LR98M28BHXA== X-UI-Out-Filterresults: notjunk:1;V01:K0:dttjMXpCygQ=:JZxuJ7NotVjpU4VVDdEgJ/ c0ScGOEo4cHSV0P0nPsbj2IDAiTIZuzIIK1HgA4cWUGSNeH+e875ZMrlMKThJaRmtSdekaiOP xTKX9YULtyAjh7vfwsCYQPVn7MUyCJd2zn6bbLXB9p032rHyzZcXagWZmCQgbvBJr45PsTewa 4a71wDhQjjSFm4AKlLZs3TZL3/c+rZYJ8k68KqRfENGYP81swjSu9v9m2OWpSIHQ6S2+S9fwT sBBKnRW/XJOXP+L4EfNJ/+lAXZHAqHEwkhNWXlKrDoiaWMnCR8zx7gegtShKjFhXmElvpQJIK 9b8739itrLDI3TWn1F3VYfpf2Sffz5yFIN0S6zgeV74HOZeNZpJPqY2hqR28E596v5fKKdfWd WLVaaBcqxGeccjArBE9acgZpnb1POHve8tk2htZwjGvShFsiSnfCZZyNPq41R4DXf9NH+5Zn4 bXISFQjlKR7xivQfoBB0AFpdqXCfUb/X6aHaHgFLXbqQ834/8VwZWDpU9L3+6cp/SL1B8PmXn suxit96v06liM7G24abeE26qz2WxT50uqUP8z4jkuu+qhlKcLt7MeJ6ckVC4UP3cEKa57P3+l gkmWiqu4pN0Wg+VfGRLdF5FDHLz4lqJTAWh6+rHyDU2NK6DE/ZmlQ9pz8Ku/sH3fm4TF869Z8 iQKI/20IRboHfk/lu7srvVD9YWNC2YJ2xWR2+Zw+UGjJO2Mlupj9hQO30jIO+i3a9Ru9IAEH1 6JABbu2vddOVR3QpQQ6J7Qs1lWaJyTvUlzS9OwDUW+7y3guHc+DTLt6vPHw= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 212.227.15.14 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:204176 Archived-At: --=-=-= Content-Type: text/plain Michael Heerdegen writes: > here is a patch that adds some missing stream operations. Resending the patch as attachment (probably the preferable way). Thanks, Michael. --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Add-some-more-basic-stream-operations.patch >From 60ae524edf7fb39791f50582a213c8601bbfb1be Mon Sep 17 00:00:00 2001 From: Michael Heerdegen Date: Thu, 2 Jun 2016 02:42:43 +0200 Subject: [PATCH] Add some more basic stream operations --- packages/stream/stream.el | 59 +++++++++++++++++++++++++++++++++++ packages/stream/tests/stream-tests.el | 32 +++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/packages/stream/stream.el b/packages/stream/stream.el index 22cecac..7728338 100644 --- a/packages/stream/stream.el +++ b/packages/stream/stream.el @@ -333,6 +333,65 @@ 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-reduce (function init stream) + "Reduce two-argument FUNCTION across STREAM starting with INIT." + (let ((res init)) + (stream-flush (seq-map (lambda (el) (setq res (funcall function res el))) stream)) + res)) + +(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." + (stream-reduce #'stream-append (stream-empty) stream-of-streams)) + +(defun stream-mapconcat (function stream separator) + "Apply FUNCTION to each element of STREAM and concat the results as strings. +In between of each pair of results, stick in SEPARATOR. This is +like `mapconcat', but for streams." + (if (stream-empty-p stream) "" + (let ((mapped (seq-map function stream))) + (stream-reduce (lambda (x y) (concat x separator y)) (stream-first mapped) (stream-rest mapped))))) (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 23a54b5..360a405 100644 --- a/packages/stream/tests/stream-tests.el +++ b/packages/stream/tests/stream-tests.el @@ -242,5 +242,37 @@ (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-reduce () + (should (eq (stream-reduce #'* 1 (seq-take (stream-range 1) 4)) 24))) + +(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)))) + +(ert-deftest stream-mapconcat-test () + (should (equal (stream-mapconcat #'capitalize (stream (list)) ",") "")) + (should (equal (stream-mapconcat #'capitalize (stream (list "a")) ",") "A")) + (should (equal (stream-mapconcat #'capitalize (stream (list "a" "b")) ",") "A,B")) + (should (equal (stream-mapconcat #'capitalize (stream (list "a" "b" "c")) ",") "A,B,C"))) + (provide 'stream-tests) ;;; stream-tests.el ends here -- 2.8.1 --=-=-=--