commit c6f2cf9dfd016366dae673e47f032c1751f61232
parent fbbb4b359a4bdf9cfcb0df60e3c12eb277bbb6fc
Author: Tomas Hlavaty <tom@logand.com>
Date:   Sun, 22 Oct 2017 08:19:30 +0200
more readers
Diffstat:
| M | rw.lisp |  |  | 113 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- | 
1 file changed, 99 insertions(+), 14 deletions(-)
diff --git a/rw.lisp b/rw.lisp
@@ -23,16 +23,21 @@
 (defpackage :rw
   (:use :cl)
   (:export :*endian*
+           :append-reader
            :bit-reader
            :byte-reader
            :byte-writer
            :char-reader
            :char-writer
            :copy
+           :count-reader
            :fibonacci-reader
            :filter-reader
            :flat-reader
+           :head-reader
            :line-reader
+           :map-reader
+           :n-reader
            :next
            :next-octets
            :next-u16
@@ -50,12 +55,12 @@
            :peek
            :peek-reader
            :reader
+           :reduce-reader
            :search-reader
-           :shorter-reader
            :skip
            :slurp
+           :tail-reader
            :till
-           :u8
            :u16
            :u16be
            :u16le
@@ -65,8 +70,8 @@
            :u32
            :u32be
            :u32le
+           :u8
            :utf8-reader
-           :wrap-reader
            :wrap-writer
            :write-octets
            :write-u16
@@ -83,7 +88,9 @@
            :write-utf8-codepoint
            :write-utf8-string
            :writer
-           :z0))
+           :z0
+           :zip-reader
+           ))
 
 (in-package :rw)
 
@@ -537,18 +544,46 @@
              (setq z1 z2
                    z2 z)))))))
 
-;;(till (peek-reader (fibonacci-reader 10))) => 0 1 1 2 3 5 8 13 21 34
+;;(slurp (fibonacci-reader 10)) => 0 1 1 2 3 5 8 13 21 34
+
+(defun head-reader (reader n)
+  (let ((i 0))
+    (lambda ()
+      (when (< i n)
+        (incf i)
+        (funcall reader)))))
+
+;;(slurp (head-reader (reader '(1 2 3 4 5)) 3))
+;;(slurp (head-reader (reader '(1 2 3 4 5)) 7))
+
+(defun tail-reader (reader n)
+  (labels ((rec ()
+             (cond
+               ((plusp n)
+                (decf n)
+                (funcall reader)
+                (rec))
+               (t
+                (funcall reader)))))
+    #'rec))
+
+;;(slurp (tail-reader (reader '(1 2 3 4 5)) 3))
+;;(slurp (tail-reader (reader '(1 2 3 4 5)) 7))
+
+;;(next (head-reader (tail-reader (reader '(1 2 3 4 5)) 2) 1))
+
+(defun n-reader (reader n)
+  (let ((i 0))
+    (lambda ()
+      (when (< i n)
+        (incf i)
+        (or (funcall reader)
+            (error "only ~s out of ~s items read" (1- i) n))))))
 
-(defun shorter-reader (reader size)
-  (if size
-      (let ((offset 0))
-        (lambda ()
-          (when (< offset size)
-            (incf offset)
-            (funcall reader))))
-      reader))
+;;(slurp (n-reader (reader '(1 2 3 4 5)) 3))
+;;(slurp (n-reader (reader '(1 2 3 4 5)) 7))
 
-(defun wrap-reader (reader fn)
+(defun map-reader (reader fn)
   (lambda ()
     (let ((z (next reader)))
       (when z
@@ -584,3 +619,53 @@
 ;; flat input octets -> cons tree -> octet-reader tree -> [writer] flat output octets
 
 ;; https://rosettacode.org/wiki/Flatten_a_list
+
+(defun append-reader (readers)
+  (labels ((rec ()
+             (when readers
+               (let ((z (next (car readers))))
+                 (cond
+                   (z)
+                   (t
+                    (pop readers)
+                    (rec)))))))
+    #'rec))
+
+;;(slurp (append-reader (list (reader "hi") (rw:reader "hello"))))
+
+(defun ref (reader n) ;; is it useful?
+  (dotimes (i n (next reader))
+    (next reader)))
+
+;;(ref (append-reader (list (reader "hi") (rw:reader "hello"))) 3)
+
+(defun reduce-reader (reader fn i)
+  (lambda ()
+    (let ((z (next reader)))
+      (when z
+        (setq i (funcall fn z i))))))
+
+;;(slurp (reduce-reader (reader '(1 2 3)) #'+ 0))
+
+(defun count-reader (reader)
+  (let ((i 0))
+    (lambda ()
+      (let ((z (next reader)))
+        (when z
+          (incf i))))))
+
+;;(slurp (count-reader (reader '(1 2 3))))
+
+(defun zip-reader (readers)
+  (lambda ()
+    (loop
+       for r in readers
+       for v = (next r)
+       unless v do (return)
+       collect v)))
+
+;;(slurp (zip-reader (list (reader '(1 2 3 4 5)) (reader '(a b c d)))))
+;;(slurp (zip-reader (list (reader '(1 2 3 4 5)) (reader '(a b c d e f)))))
+
+;; ? readers -> choose one based on some criterion?  flat-reader + sort?
+;; mux-reader