[racket-dev] [PATCH] add in-slice sequence

From: David Vanderson (david.vanderson at gmail.com)
Date: Fri Dec 9 02:46:29 EST 2011

Hello,

I was trying to write some code to process a few items at a time from a 
list.  Nothing I came up with looked great, so I wrote an "in-slice" 
sequence function:

 > (for/list ([e (in-slice 3 (in-range 8))]) e)
'((0 1 2) (3 4 5) (6 7))

Patch below.  Comments?

Thanks,
Dave



diff --git a/collects/racket/private/for.rkt 
b/collects/racket/private/for.rkt
index 88733ca..9e032fa 100644
--- a/collects/racket/private/for.rkt
+++ b/collects/racket/private/for.rkt
@@ -51,6 +51,7 @@

               in-sequences
               in-cycle
+             in-slice
               in-parallel
               in-values-sequence
               in-values*-sequence
@@ -984,10 +985,30 @@
      (if (and (pair? sequences) (null? (cdr sequences)))
          (car sequences)
          (append-sequences sequences #f)))
+
    (define (in-cycle . sequences)
      (check-sequences 'in-cycle sequences)
      (append-sequences sequences #t))

+  (define (in-slice k seq)
+    (when (not (exact-positive-integer? k))
+      (raise (exn:fail:contract "in-slice length must be a positive 
integer"
+                              (current-continuation-marks))))
+    (check-sequences 'in-slice (list seq))
+    (make-do-sequence
+     (lambda ()
+       (define-values (more? get) (sequence-generate seq))
+       (values
+        (lambda (_)
+          (for/list ((i k)
+                     #:when (more?))
+            (get)))
+        values
+        #f
+        #f
+        (lambda (val) (0 . < . (length val)))
+        #f))))
+
    (define (in-parallel . sequences)
      (check-sequences 'in-parallel sequences)
      (if (= 1 (length sequences))
diff --git a/collects/scribblings/reference/sequences.scrbl 
b/collects/scribblings/reference/sequences.scrbl
index d3ecdfb..6192761 100644
--- a/collects/scribblings/reference/sequences.scrbl
+++ b/collects/scribblings/reference/sequences.scrbl
@@ -298,6 +298,16 @@ in the sequence.
    demanded---or even when the sequence is @tech{initiate}d, if all
    @racket[seq]s are initially empty.}

+ at defproc[(in-slice [length exact-positive-integer?] [seq sequence?]) 
sequence?]{
+  Returns a sequence where each element is a list with @racket[length] 
elements
+  from the given sequence.
+
+  @examples[
+  (for/list ([e (in-slice 3 (in-range 8))]) e)
+  ]
+
+  }
+
  @defproc[(in-parallel [seq sequence?] ...) sequence?]{
    Returns a sequence where each element has as many values as the number
    of supplied @racket[seq]s; the values, in order, are the values of
diff --git a/collects/tests/racket/for.rktl b/collects/tests/racket/for.rktl
index 691e309..6c883b8 100644
--- a/collects/tests/racket/for.rktl
+++ b/collects/tests/racket/for.rktl
@@ -84,6 +84,15 @@
  (test #t sequence? (in-cycle))
  (test #t sequence? (in-cycle '()))

+(test #t sequence? (in-slice 1 '()))
+(test '() 'empty-seq (for/list ([v (in-slice 1 '())]) v))
+(test '((0 1)) 'single-slice (for/list ([v (in-slice 3 (in-range 2))]) v))
+(test-sequence [((0 1 2) (3 4 5))] (in-slice 3 (in-range 6)))
+(test-sequence [((0 1 2) (3 4 5) (6 7))] (in-slice 3 (in-range 8)))
+(test-sequence [((0 1 2) (3 4 5) (6 7 8)) (0 1 2)]
+                (in-parallel (in-slice 3 (in-naturals)) (in-range 3)))
+(err/rt-test (for/list ([x (in-slice 0 (in-range 8))]) x) 
exn:fail:contract?)
+
  (test-sequence [(0 1 2) (a b c)] (in-parallel (in-range 3) (in-list 
'(a b c))))
  (test-sequence [(0 1 2) (a b c)] (in-parallel (in-range 10) (in-list 
'(a b c))))
  (test-sequence [(0 1 2) (a b c)] (in-parallel (in-range 3) (in-list 
'(a b c d))))



Posted on the dev mailing list.