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

From: David Vanderson (david.vanderson at gmail.com)
Date: Thu Dec 15 22:47:44 EST 2011

I only got one comment (thanks John), so I'm resending for more 
feedback.  Is there any interest in adding this, or does everybody do it 
a better/different way?


A more motivated example would be showing a list of products on a 
webpage in batches:

(define products '(a b c d e f g))
(for/list ([s (in-slice 3 products)])
   `(ul ,@(for/list ([e s])
             `(li ,e))))

Thanks,
Dave

On 12/09/2011 02:46 AM, David Vanderson wrote:
> 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.