[racket-dev] [PATCH] add in-slice sequence
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))))