[racket-dev] [plt] Push #20857: master branch updated

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Thu Aug 12 16:15:35 EDT 2010

Here's the next batch of changes based on the recent article.

I didn't do every list function because some of them don't make as
much sense to me, but I think I've given a framework for anyone who
has more functions they think we need to see how to implement it and
then where to put the tests, etc. If anyone has suggestions for
another function, let me know.

There's a few things I wanted to do that I didn't know how:

- for/sequence that constructs the sequence lazily. (The exist
for/fold/derived looks like it can't deal with the laziness and it
seems very bad to duplicate the macro code.)

- sequence/c -- I know how I'd implement it, but I don't know where it
would be allowed to go.

As a final note, I don't intend this to be a mere pandering to this
blog post. When I was reading the blog post I found myself saying, "Ya
but you could implement that so easily" or "Ya, it is annoying to use
that pattern", etc. Hearing myself say that told me that I've always
wanted many of these functions but I always implemented them in a
one-off fashion or used a boilerplate pattern.

Jay

On Thu, Aug 12, 2010 at 2:10 PM,  <jay at racket-lang.org> wrote:
> jay has updated `master' from 1ebdb6a90b to fae0cb2c99.
>  http://git.racket-lang.org/plt/1ebdb6a90b..fae0cb2c99
>
> =====[ 11 Commits ]=====================================================
>
> Directory summary:
>  28.2% collects/racket/private/
>   7.3% collects/racket/
>  32.1% collects/scribblings/reference/
>  20.8% collects/tests/racket/
>   3.1% collects/tests/unstable/
>   4.4% collects/unstable/scribblings/
>   3.9% collects/unstable/
>
> ~~~~~~~~~~
>
> f23daa3 Jay McCarthy <jay at racket-lang.org> 2010-08-12 08:12
> :
> | Rename hash-range and domain to keys and values
> :
>  M collects/racket/private/hash.rkt            |    8 ++++----
>  M collects/scribblings/reference/hashes.scrbl |    8 ++++----
>  M collects/tests/racket/basic.rktl            |    8 ++++----
>
> ~~~~~~~~~~
>
> a8fc09b Jay McCarthy <jay at racket-lang.org> 2010-08-12 08:23
> :
> | Adding dict-keys,values,->list
> :
>  M collects/racket/dict.rkt                   |   18 ++++++++++++++++
>  M collects/scribblings/reference/dicts.scrbl |   28 +++++++++++++++++++++++++
>  M collects/tests/racket/dict.rktl            |    4 +++
>
> ~~~~~~~~~~
>
> 2d1787a Jay McCarthy <jay at racket-lang.org> 2010-08-12 08:33
> :
> | Add dict-set*
> :
>  M collects/racket/dict.rkt                   |   20 ++++++++++
>  M collects/scribblings/reference/dicts.scrbl |   51 +++++++++++++++++++++++++
>  M collects/tests/racket/dict.rktl            |   17 ++++++++
>
> ~~~~~~~~~~
>
> bdc26b5 Jay McCarthy <jay at racket-lang.org> 2010-08-12 08:53
> :
> | Adding dict-ref bang
> :
>  M collects/racket/dict.rkt                   |   10 ++++++++++
>  M collects/scribblings/reference/dicts.scrbl |   20 ++++++++++++++++++++
>  M collects/tests/racket/dict.rktl            |   13 ++++++++++++-
>
> ~~~~~~~~~~
>
> 958c771 Jay McCarthy <jay at racket-lang.org> 2010-08-12 08:55
> :
> | Removing dict functions from unstable
> :
>  M collects/tests/unstable/dict.rkt         |   14 +-------
>  M collects/unstable/dict.rkt               |   29 ----------------
>  M collects/unstable/scribblings/dict.scrbl |   48 ---------------------------
>
> ~~~~~~~~~~
>
> d047557 Jay McCarthy <jay at racket-lang.org> 2010-08-12 09:00
> :
> | Adding dict-has-key? and updating unstable
> :
>  M collects/racket/dict.rkt                   |    5 +++++
>  M collects/scribblings/reference/dicts.scrbl |   15 +++++++++++++++
>  M collects/tests/racket/dict.rktl            |    2 ++
>  M collects/tests/unstable/dict.rkt           |    5 +----
>  M collects/unstable/dict.rkt                 |   16 +---------------
>  M collects/unstable/scribblings/dict.scrbl   |   12 ------------
>
> ~~~~~~~~~~
>
> 3fe91f0 Jay McCarthy <jay at racket-lang.org> 2010-08-12 09:24
> :
> | Adding vector-set* and dict-set* exn tests
> :
>  M collects/racket/vector.rkt                   |   10 +++++++++-
>  M collects/scribblings/reference/vectors.scrbl |   11 ++++++++++-
>  M collects/tests/racket/dict.rktl              |    3 +++
>  M collects/tests/racket/vector.rktl            |   11 ++++++++++-
>
> ~~~~~~~~~~
>
> 2751ace Jay McCarthy <jay at racket-lang.org> 2010-08-12 13:13
> :
> | Adding more sequence operators
> :
>  M collects/racket/list.rkt                       |   10 +--
>  M collects/racket/private/base.rkt               |    4 +-
>  M collects/racket/private/list.rkt               |   17 ++++-
>  A collects/racket/private/sequence.rkt
>  M collects/scribblings/reference/sequences.scrbl |   83 +++++++++++++++++
>  M collects/tests/racket/for.rktl                 |  101 +++++++++++++++++++++
>
> ~~~~~~~~~~
>
> 383465a Jay McCarthy <jay at racket-lang.org> 2010-08-12 13:16
> :
> | Removing reference to sequence/c
> :
>  M collects/scribblings/reference/sequences.scrbl |   32 ++++++++++----------
>
> ~~~~~~~~~~
>
> 8c32de3 Jay McCarthy <jay at racket-lang.org> 2010-08-12 13:33
> :
> | Adding sequence support for mlists and more sequence xrefs
> :
>  M collects/racket/private/for.rkt                |   36 ++++++++++++++++++++-
>  M collects/scribblings/reference/dicts.scrbl     |    4 ++
>  M collects/scribblings/reference/mpairs.scrbl    |    4 ++
>  M collects/scribblings/reference/sequences.scrbl |   18 +++++++++--
>  M collects/scribblings/reference/sets.scrbl      |    8 +++--
>  M collects/tests/racket/for.rktl                 |    5 ++-
>
> ~~~~~~~~~~
>
> fae0cb2 Jay McCarthy <jay at racket-lang.org> 2010-08-12 14:09
> :
> | A few fixes to the documentation
> :
>  M collects/scribblings/reference/sequences.scrbl |    2 +-
>  M collects/scribblings/reference/vectors.scrbl   |   22 ++++++++++----------
>
> =====[ Overall Diff ]===================================================
>
> collects/racket/dict.rkt
> ~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/racket/dict.rkt
> +++ NEW/collects/racket/dict.rkt
> @@ -9,9 +9,13 @@
>          dict-can-remove-keys?
>          dict-can-functional-set?
>
> +         dict-has-key?
>          dict-ref
> +         dict-ref!
>          dict-set!
> +         dict-set*!
>          dict-set
> +         dict-set*
>          dict-update!
>          dict-update
>          dict-remove!
> @@ -29,6 +33,10 @@
>          in-dict-keys
>          in-dict-values
>          in-dict-pairs
> +
> +         dict-keys
> +         dict-values
> +         dict->list
>
>          (rename-out [create-custom-hash make-custom-hash]
>                      [create-immutable-custom-hash make-immutable-custom-hash])
> @@ -185,6 +193,10 @@
>                #t))
>       (raise-type-error 'dict-can-functional-set? "dict" d)))
>
> +(define (dict-has-key? d k)
> +  (define not-there (gensym))
> +  (not (eq? not-there (dict-ref d k not-there))))
> +
>  (define dict-ref
>   (case-lambda
>    [(d key)
> @@ -224,6 +236,15 @@
>      [else
>       (raise-type-error 'dict-ref "dict" 0 d key default)])]))
>
> +(define (dict-ref! d key new)
> +  (define not-there (gensym))
> +  (define v (dict-ref d key not-there))
> +  (if (eq? not-there v)
> +      (let ([n (if (procedure? new) (new) new)])
> +        (dict-set! d key n)
> +        n)
> +      v))
> +
>  (define (dict-set! d key val)
>   (cond
>    [(hash? d) (hash-set! d key val)]
> @@ -238,6 +259,14 @@
>    [else
>     (raise-type-error 'dict-set! "dict" 0 d key val)]))
>
> +(define (dict-set*! d . pairs)
> +  (unless (even? (length pairs))
> +    (error 'dict-set*! "expected an even number of association elements, but received an odd number: ~e" pairs))
> +  (let loop ([pairs pairs])
> +    (unless (null? pairs)
> +      (dict-set! d (car pairs) (cadr pairs))
> +      (loop (cddr pairs)))))
> +
>  (define (dict-set d key val)
>   (cond
>    [(hash? d) (hash-set d key val)]
> @@ -260,6 +289,16 @@
>    [else
>     (raise-type-error 'dict-set "dict" 0 d key val)]))
>
> +(define (dict-set* d . pairs)
> +    (unless (even? (length pairs))
> +      (error 'dict-set* "expected an even number of association elements, but received an odd number: ~e" pairs))
> +    (let loop ([d d]
> +               [pairs pairs])
> +      (if (null? pairs)
> +          d
> +          (loop (dict-set d (car pairs) (cadr pairs))
> +                (cddr pairs)))))
> +
>  (define dict-update!
>   (case-lambda
>    [(d key xform)
> @@ -459,6 +498,20 @@
>   (for ([(k v) (in-dict d)])
>     (f k v)))
>
> +(define (dict-keys d)
> +  (for/list ([k (in-dict-keys d)])
> +    k))
> +
> +(define (dict-values d)
> +  (for/list ([v (in-dict-values d)])
> +    v))
> +
> +(define (dict->list d)
> +  (for/list ([k*v (in-dict-pairs d)])
> +    k*v))
> +
> +
> +
>  ;; ----------------------------------------
>
>  (struct hash-box (key))
>
> collects/racket/list.rkt
> ~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/racket/list.rkt
> +++ NEW/collects/racket/list.rkt
> @@ -1,5 +1,5 @@
>  #lang scheme/base
> -
> +(require (only-in "private/list.rkt" split-at))
>  (provide first second third fourth fifth sixth seventh eighth ninth tenth
>
>          last-pair last rest
> @@ -113,14 +113,6 @@
>     (raise-type-error 'drop "non-negative exact integer" n))
>   (or (drop* list n) (too-large 'drop list n)))
>
> -(define (split-at list0 n0)
> -  (unless (exact-nonnegative-integer? n0)
> -    (raise-type-error 'split-at "non-negative exact integer" n0))
> -  (let loop ([list list0] [n n0] [pfx '()])
> -    (cond [(zero? n) (values (reverse pfx) list)]
> -          [(pair? list) (loop (cdr list) (sub1 n) (cons (car list) pfx))]
> -          [else (too-large 'take list0 n0)])))
> -
>  ;; take/drop-right are originally from srfi-1, uses the same lead-pointer trick
>
>  (define (take-right list n)
>
> collects/racket/private/base.rkt
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/racket/private/base.rkt
> +++ NEW/collects/racket/private/base.rkt
> @@ -1,6 +1,7 @@
>  (module base "pre-base.rkt"
>
> -  (#%require "hash.rkt"
> +  (#%require "sequence.rkt"
> +             "hash.rkt"
>              "list.rkt"
>              "string.rkt"
>              "stxcase-scheme.rkt"
> @@ -22,6 +23,7 @@
>                               regexp-replace*
>                               new-apply-proc)
>              struct
> +             (all-from "sequence.rkt")
>              (all-from "hash.rkt")
>              (all-from "list.rkt")
>              (all-from-except "string.rkt"
>
> collects/racket/private/for.rkt
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/racket/private/for.rkt
> +++ NEW/collects/racket/private/for.rkt
> @@ -29,6 +29,7 @@
>              (rename *in-range in-range)
>              (rename *in-naturals in-naturals)
>              (rename *in-list in-list)
> +             (rename *in-mlist in-mlist)
>              (rename *in-vector in-vector)
>              (rename *in-string in-string)
>              (rename *in-bytes in-bytes)
> @@ -318,6 +319,7 @@
>   (define (sequence? v)
>     (or (do-sequence? v)
>         (list? v)
> +        (mpair? v)
>         (vector? v)
>         (string? v)
>         (bytes? v)
> @@ -329,6 +331,7 @@
>     (cond
>       [(do-sequence? v) ((do-sequence-ref v 0))]
>       [(list? v) (:list-gen v)]
> +      [(mpair? v) (:mlist-gen v)]
>       [(vector? v) (:vector-gen v 0 (vector-length v) 1)]
>       [(string? v) (:string-gen v 0 (string-length v) 1)]
>       [(bytes? v) (:bytes-gen v 0 (bytes-length v) 1)]
> @@ -378,9 +381,15 @@
>   (define (in-list l)
>     ;; (unless (list? l) (raise-type-error 'in-list "list" l))
>     (make-do-sequence (lambda () (:list-gen l))))
> -
> +
>   (define (:list-gen l)
>     (values car cdr l pair? void void))
> +
> +  (define (in-mlist l)
> +    (make-do-sequence (lambda () (:mlist-gen l))))
> +
> +  (define (:mlist-gen l)
> +    (values mcar mcdr l mpair? void void))
>
>   (define (check-ranges who start stop step)
>     (unless (exact-nonnegative-integer? start) (raise-type-error who "exact non-negative integer" start))
> @@ -1073,6 +1082,31 @@
>              ;; loop args -- ok to use unsafe-cdr, since car passed
>              ((unsafe-cdr lst)))]]
>         [_ #f])))
> +
> +  (define-sequence-syntax *in-mlist
> +    (lambda () #'in-mlist)
> +    (lambda (stx)
> +      (syntax-case stx ()
> +        [[(id) (_ lst-expr)]
> +         #'[(id)
> +            (:do-in
> +             ;;outer bindings
> +             ([(lst) lst-expr])
> +             ;; outer check
> +             (void) ; (unless (list? lst) (in-list lst))
> +             ;; loop bindings
> +             ([lst lst])
> +             ;; pos check
> +             (not (null? lst))
> +             ;; inner bindings
> +             ([(id) (mcar lst)])
> +             ;; pre guard
> +             #t
> +             ;; post guard
> +             #t
> +             ;; loop args
> +             ((mcdr lst)))]]
> +        [_ #f])))
>
>   (define-for-syntax (vector-like-gen vector?-id
>                                       unsafe-vector-length-id
>
> collects/racket/private/hash.rkt
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/racket/private/hash.rkt
> +++ NEW/collects/racket/private/hash.rkt
> @@ -1,8 +1,8 @@
>  (module hash "pre-base.rkt"
> -  (define (hash-domain table)
> +  (define (hash-keys table)
>     (hash-map table (λ (k v) k)))
>
> -  (define (hash-range table)
> +  (define (hash-values table)
>     (hash-map table (λ (k v) v)))
>
>   (define (hash->list table)
> @@ -26,8 +26,8 @@
>         (hash-set! table (car pairs) (cadr pairs))
>         (loop (cddr pairs)))))
>
> -  (provide hash-domain
> -           hash-range
> +  (provide hash-keys
> +           hash-values
>            hash->list
>            hash-set*
>            hash-set*!))
> \ No newline at end of file
>
> collects/racket/private/list.rkt
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/racket/private/list.rkt
> +++ NEW/collects/racket/private/list.rkt
> @@ -1,7 +1,9 @@
>
>  (module list "pre-base.rkt"
>
> -  (provide foldl
> +  (provide split-at
> +
> +           foldl
>            foldr
>
>            remv
> @@ -24,6 +26,19 @@
>            build-list
>
>            compose)
> +
> +  (define (split-at list0 n0)
> +    (unless (exact-nonnegative-integer? n0)
> +      (raise-type-error 'split-at "non-negative exact integer" n0))
> +    (let loop ([list list0] [n n0] [pfx '()])
> +      (cond [(zero? n) (values (reverse pfx) list)]
> +            [(pair? list) (loop (cdr list) (sub1 n) (cons (car list) pfx))]
> +            [else
> +             (raise-mismatch-error
> +              'split-at
> +              (format "index ~e too large for list~a: "
> +                      n0 (if (list? list0) "" " (not a proper list)"))
> +              list0)])))
>
>   (#%require (rename "sort.rkt" raw-sort sort)
>              (for-syntax "stxcase-scheme.rkt"))
>
> collects/racket/private/sequence.rkt
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- /dev/null
> +++ NEW/collects/racket/private/sequence.rkt
> @@ -0,0 +1,247 @@
> +(module sequence "pre-base.rkt"
> +  (require "list.rkt")
> +
> +  (define empty-seqn
> +    (make-do-sequence
> +     (λ ()
> +       (values
> +        void
> +        void
> +        void
> +        (λ (pos) #f)
> +        (λ (val) #t)
> +        (λ (pos val) #t)))))
> +
> +  (define (seqn->list s)
> +    (for/list ([v s]) v))
> +
> +  (define-syntax-rule (-seqn-cons vs s)
> +    (make-do-sequence
> +     (λ ()
> +       (define-values (more? next) (sequence-generate s))
> +       (values
> +        (λ (pos)
> +          (if (zero? pos)
> +              vs
> +              (next)))
> +        (λ (pos) (if (zero? pos) 1 pos))
> +        0
> +        (λ (pos)
> +          (or (zero? pos) (more?)))
> +        (λ _ #t)
> +        (λ _ #t)))))
> +  (define seqn-cons
> +    (case-lambda
> +      [()
> +       (error 'seqn-cons "expects a sequence to extend, but received no arguments")]
> +      [(s)
> +       (-seqn-cons (values) s)]
> +      [(v s)
> +       (-seqn-cons (values v) s)]
> +      [vs*s
> +       (define-values (vs sl) (split-at vs*s (sub1 (length vs*s))))
> +       (-seqn-cons (apply values vs) (car sl))]))
> +
> +  (define (seqn-first s)
> +    (define-values (more? next) (sequence-generate s))
> +    (unless (more?)
> +      (error 'seqn-first "expects a sequence with at least one element"))
> +    (next))
> +
> +  (define (seqn-rest s)
> +    (make-do-sequence
> +     (λ ()
> +       (define-values (more? next) (sequence-generate s))
> +       (unless (more?)
> +         (error 'seqn-rest "expects a sequence with at least one element"))
> +       (next)
> +       (values
> +        (λ (pos) (next))
> +        (λ (x) x)
> +        0
> +        (λ (pos) (more?))
> +        (λ _ #t)
> +        (λ _ #t)))))
> +
> +  (define (seqn-length s)
> +    (define-values (more? next) (sequence-generate s))
> +    (let loop ([i 0])
> +      (if (more?)
> +          (begin (next) (loop (add1 i)))
> +          i)))
> +
> +  (define (seqn-ref s i)
> +    (unless (and (exact-integer? i) (i . >= . 0))
> +      (error 'seqn-ref "expects an exact non-negative index, but got ~e" i))
> +    (define-values (more? next) (sequence-generate s))
> +    (let loop ([n i])
> +      (cond
> +        [(zero? n)
> +         (next)]
> +        [(more?)
> +         (next)
> +         (loop (sub1 n))]
> +        [else
> +         (error 'seqn-ref "expects a sequence with at least ~e element(s)" i)])))
> +
> +  (define (seqn-tail s i)
> +    (unless (and (exact-integer? i) (i . >= . 0))
> +      (error 'seqn-tail "expects an exact non-negative index, but got ~e" i))
> +    (make-do-sequence
> +     (λ ()
> +       (define-values (more? next) (sequence-generate s))
> +       (let loop ([n i])
> +         (unless (zero? n)
> +           (unless (more?)
> +             (error 'seqn-tail "expects a sequence with at least ~e element(s)" i))
> +           (next)
> +           (loop (sub1 n))))
> +       (values
> +        (λ (pos) (next))
> +        (λ (x) x)
> +        0
> +        (λ (pos) (more?))
> +        (λ _ #t)
> +        (λ _ #t)))))
> +
> +  (define (-seqn-append s0 l)
> +    (if (null? l)
> +        s0
> +        (make-do-sequence
> +         (λ ()
> +           (define remaining l)
> +           (define (next-pos pos)
> +             (cond
> +               [(more?)
> +                #t]
> +               [(null? remaining)
> +                #f]
> +               [else
> +                (let*-values ([(s1) (car remaining)]
> +                              [(next-more? next-next) (sequence-generate s1)])
> +                  (set! more? next-more?)
> +                  (set! next next-next)
> +                  (set! remaining (cdr remaining))
> +                  (next-pos pos))]))
> +           (define-values (more? next) (sequence-generate s0))
> +           (values
> +            (λ (pos) (next))
> +            (λ (x) x)
> +            0
> +            next-pos
> +            (λ _ #t)
> +            (λ _ #t))))))
> +
> +  (define (seqn-append . l)
> +    (unless (andmap sequence? l)
> +      (error 'seqn-append "expects only sequence arguments, given ~e" l))
> +    (-seqn-append empty-seqn l))
> +
> +  (define (seqn-map f s)
> +    (unless (procedure? f)
> +      (error 'seqn-map "expects a procedure as the first argument, given ~e" f))
> +    (make-do-sequence
> +     (λ ()
> +       (define-values (more? next) (sequence-generate s))
> +       (values
> +        (λ (pos) (call-with-values next f))
> +        (λ (x) x)
> +        0
> +        (λ (pos) (more?))
> +        (λ _ #t)
> +        (λ _ #t)))))
> +
> +  (define (seqn-andmap f s)
> +    (define-values (more? next) (sequence-generate s))
> +    (let loop ()
> +      (if (more?)
> +          (and (call-with-values next f) (loop))
> +          #t)))
> +
> +  (define (seqn-ormap f s)
> +    (define-values (more? next) (sequence-generate s))
> +    (let loop ()
> +      (if (more?)
> +          (or (call-with-values next f) (loop))
> +          #f)))
> +
> +  (define (seqn-for-each f s)
> +    (define-values (more? next) (sequence-generate s))
> +    (let loop ()
> +      (when (more?)
> +        (call-with-values next f)
> +        (loop))))
> +
> +  (define (seqn-fold f i s)
> +    (define-values (more? next) (sequence-generate s))
> +    (let loop ([i i])
> +      (if (more?)
> +          (loop (call-with-values next (λ e (apply f i e))))
> +          i)))
> +
> +  (define (seqn-filter f s)
> +    (unless (procedure? f)
> +      (error 'seqn-filter "expects a procedure as the first argument, given ~e" f))
> +    (make-do-sequence
> +     (λ ()
> +       (define-values (more? next) (sequence-generate s))
> +       (define next-vs #f)
> +       (define (next-pos pos)
> +         (if (more?)
> +             (call-with-values next
> +                               (λ vs
> +                                 (if (apply f vs)
> +                                     (begin (set! next-vs vs)
> +                                            #t)
> +                                     (next-pos pos))))
> +             #f))
> +       (values
> +        (λ (pos) (apply values next-vs))
> +        (λ (x) x)
> +        0
> +        next-pos
> +        (λ _ #t)
> +        (λ _ #t)))))
> +
> +  (define (seqn-add-between s e)
> +    (make-do-sequence
> +     (λ ()
> +       (define-values (more? next) (sequence-generate s))
> +       (values
> +        (λ (pos)
> +          (if pos
> +              (next)
> +              e))
> +        not
> +        #t
> +        (λ (pos)
> +          (if pos
> +              (more?)
> +              #t))
> +        (λ _ #t)
> +        (λ _ #t)))))
> +
> +  (define (seqn-count s)
> +    (define-values (more? next) (sequence-generate s))
> +    (let loop ([n 0])
> +      (if (more?)
> +          (begin (next) (loop (add1 n)))
> +          n)))
> +
> +  (provide empty-seqn
> +           seqn->list
> +           seqn-cons
> +           seqn-first
> +           seqn-rest
> +           seqn-length
> +           seqn-ref
> +           seqn-tail
> +           seqn-append
> +           seqn-map
> +           seqn-andmap
> +           seqn-ormap
> +           seqn-for-each
> +           seqn-fold
> +           seqn-filter
> +           seqn-add-between
> +           seqn-count))
> \ No newline at end of file
>
> collects/racket/vector.rkt
> ~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/racket/vector.rkt
> +++ NEW/collects/racket/vector.rkt
> @@ -1,6 +1,6 @@
>  #lang racket/base
>
> -(provide vector-copy vector-map vector-map! vector-append
> +(provide vector-set*! vector-copy vector-map vector-map! vector-append
>          vector-take vector-drop vector-split-at
>          vector-take-right vector-drop-right vector-split-at-right
>          vector-filter vector-filter-not
> @@ -8,6 +8,14 @@
>          vector-member vector-memq vector-memv)
>  (require racket/unsafe/ops)
>
> +(define (vector-set*! v . pairs)
> +  (unless (even? (length pairs))
> +    (error 'vector-set*! "expected an even number of association elements, but received an odd number: ~e" pairs))
> +  (let loop ([pairs pairs])
> +    (unless (null? pairs)
> +      (vector-set! v (car pairs) (cadr pairs))
> +      (loop (cddr pairs)))))
> +
>  ;; unchecked version of `vector-copy'
>  ;; used at the implementation of many functions in this file
>  (define (vector-copy* v start end)
>
> collects/scribblings/reference/dicts.scrbl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/scribblings/reference/dicts.scrbl
> +++ NEW/collects/scribblings/reference/dicts.scrbl
> @@ -24,6 +24,10 @@ values. The following datatypes are all dictionaries:
>
>  ]
>
> +A dictionary can be used as a two-valued sequence (see
> + at secref["sequences"]). The associations of the dictionary serve as elements
> +of the sequence. See also @scheme[in-dict], @scheme[in-dict-keys], and @scheme[in-dict-values].
> +
>  @note-lib[racket/dict]
>
>  @defproc[(dict? [v any/c]) boolean?]{
> @@ -110,6 +114,33 @@ h
>  v
>  ]}
>
> + at defproc[(dict-set*! [dict (and/c dict? (not/c immutable?))]
> +                     [key any/c]
> +                     [v any/c]
> +                     ...
> +                     ...) void?]{
> +
> +Maps each @scheme[key] to each @scheme[v] in @scheme[dict], overwriting any
> +existing mapping for each @scheme[key]. The update can fail with a
> + at scheme[exn:fail:contract] exception if @scheme[dict] is not mutable
> +or if any @scheme[key] is not an allowed key for the dictionary (e.g., not
> +an exact integer in the appropriate range when @scheme[dict] is a
> + at tech{vector}). The update takes place from the left, so later mappings overwrite
> +earlier mappings.
> +
> + at examples[
> +#:eval dict-eval
> +(define h (make-hash))
> +(dict-set*! h 'a "apple" 'b "banana")
> +h
> +(define v1 (vector #f #f #f))
> +(dict-set*! v1 0 "apple" 1 "banana")
> +v1
> +(define v2 (vector #f #f #f))
> +(dict-set*! v2 0 "apple" 0 "banana")
> +v2
> +]}
> +
>
>  @defproc[(dict-set [dict (and/c dict? immutable?)]
>                    [key any/c]
> @@ -131,6 +162,45 @@ dictionary.
>  (dict-set '((a . "apple") (b . "beer")) 'b "banana")
>  ]}
>
> + at defproc[(dict-set* [dict (and/c dict? immutable?)]
> +                    [key any/c]
> +                    [v any/c]
> +                    ...
> +                    ...)
> +          (and/c dict? immutable?)]{
> +
> +Functionally extends @scheme[dict] by mapping each @scheme[key] to
> +each @scheme[v], overwriting any existing mapping for each @scheme[key], and
> +returning an extended dictionary. The update can fail with a
> + at scheme[exn:fail:contract] exception if @scheme[dict] does not support
> +functional extension or if any @scheme[key] is not an allowed key for the
> +dictionary. The update takes place from the left, so later mappings overwrite
> +earlier mappings.
> +
> + at examples[
> +#:eval dict-eval
> +(dict-set* #hash() 'a "apple" 'b "beer")
> +(dict-set* #hash((a . "apple") (b . "beer")) 'b "banana" 'a "anchor")
> +(dict-set* '() 'a "apple" 'b "beer")
> +(dict-set* '((a . "apple") (b . "beer")) 'b "banana" 'a "anchor")
> +(dict-set* '((a . "apple") (b . "beer")) 'b "banana" 'b "balistic")
> +]}
> +
> + at defproc[(dict-has-key? [dict dict?] [key any/c])
> +         boolean?]{
> +
> +Returns @scheme[#t] if @scheme[dict] contains a value for the given
> + at scheme[key], @scheme[#f] otherwise.
> +
> + at examples[
> +#:eval dict-eval
> +(dict-has-key? #hash((a . "apple") (b . "beer")) 'a)
> +(dict-has-key? #hash((a . "apple") (b . "beer")) 'c)
> +(dict-has-key? '((a . "apple") (b . "banana")) 'b)
> +(dict-has-key? #("apple" "banana") 1)
> +(dict-has-key? #("apple" "banana") 3)
> +(dict-has-key? #("apple" "banana") -3)
> +]}
>
>  @defproc[(dict-ref [dict dict?]
>                    [key any/c]
> @@ -161,7 +231,27 @@ result:
>  (dict-ref #("apple" "banana") -3 #f)
>  ]}
>
> + at defproc[(dict-ref! [dict dict?]
> +                    [key any/c]
> +                    [to-set any/c])
> +         any]{
> +
> +Returns the value for @scheme[key] in @scheme[dict]. If no value
> +is found for @scheme[key], then @scheme[to-set] determines the
> +result as in @scheme[dict-ref] (i.e., it is either a thunk that computes a value
> +or a plain value), and this result is stored in @scheme[dict] for the
> + at scheme[key].  (Note that if @scheme[to-set] is a thunk, it is not
> +invoked in tail position.)
>
> + at examples[
> +#:eval dict-eval
> +(dict-ref! (make-hasheq '((a . "apple") (b . "beer"))) 'a)
> +(dict-ref! (make-hasheq '((a . "apple") (b . "beer"))) 'c 'cabbage)
> +(define h (make-hasheq '((a . "apple") (b . "beer"))))
> +(dict-ref h 'c)
> +(dict-ref! h 'c (λ () 'cabbage))
> +(dict-ref h 'c)
> +]}
>
>  @defproc[(dict-update! [dict (and/c dict? (not/c immutable?))]
>                        [key any/c]
> @@ -404,7 +494,35 @@ key and value as separate values for each element).
>   p)
>  ]}
>
> + at defproc[(dict-keys [dict dict?]) list?]{
> +Returns a list of the keys from
> + at scheme[dict] in an unspecified order.
> +
> + at examples[
> +#:eval dict-eval
> +(define h #hash((a . "apple") (b . "banana")))
> +(dict-keys h)
> +]}
> +
> + at defproc[(dict-values [dict dict?]) list?]{
> +Returns a list of the values from
> + at scheme[dict] in an unspecified order.
> +
> + at examples[
> +#:eval dict-eval
> +(define h #hash((a . "apple") (b . "banana")))
> +(dict-values h)
> +]}
> +
> + at defproc[(dict->list [dict dict?]) list?]{
> +Returns a list of the associations from
> + at scheme[dict] in an unspecified order.
>
> + at examples[
> +#:eval dict-eval
> +(define h #hash((a . "apple") (b . "banana")))
> +(dict->list h)
> +]}
>
>  @defthing[prop:dict struct-type-property?]{
>
>
> collects/scribblings/reference/hashes.scrbl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/scribblings/reference/hashes.scrbl
> +++ NEW/collects/scribblings/reference/hashes.scrbl
> @@ -330,19 +330,19 @@ new value.
>
>  @see-also-concurrency-caveat[]}
>
> - at defproc[(hash-domain [hash hash?])
> + at defproc[(hash-keys [hash hash?])
>          (listof any/c)]{
>  Returns a list of the keys of @scheme[hash] in an unspecified order.
>
>  See @scheme[hash-map] for information about modifying @scheme[hash]
> -during @scheme[hash-domain]. @see-also-concurrency-caveat[]}
> +during @scheme[hash-keys]. @see-also-concurrency-caveat[]}
>
> - at defproc[(hash-range [hash hash?])
> + at defproc[(hash-values [hash hash?])
>          (listof any/c)]{
>  Returns a list of the values of @scheme[hash] in an unspecified order.
>
>  See @scheme[hash-map] for information about modifying @scheme[hash]
> -during @scheme[hash-range]. @see-also-concurrency-caveat[]}
> +during @scheme[hash-values]. @see-also-concurrency-caveat[]}
>
>  @defproc[(hash->list [hash hash?])
>          (listof (cons/c any/c any/c))]{
>
> collects/scribblings/reference/mpairs.scrbl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/scribblings/reference/mpairs.scrbl
> +++ NEW/collects/scribblings/reference/mpairs.scrbl
> @@ -20,6 +20,10 @@ list. Instead of programming with mutable pairs and mutable lists,
>  data structures such as pairs, lists, and hash tables are practically
>  always better choices.
>
> +A @tech{mutable list} can be used as a single-valued sequence (see
> + at secref["sequences"]). The elements of the @tech{mutable list} serve as elements
> +of the sequence. See also @scheme[in-mlist].
> +
>  @; ----------------------------------------
>  @section{Mutable Pair Constructors and Selectors}
>
>
> collects/scribblings/reference/sequences.scrbl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/scribblings/reference/sequences.scrbl
> +++ NEW/collects/scribblings/reference/sequences.scrbl
> @@ -2,7 +2,8 @@
>  @(require "mz.ss"
>           (for-syntax racket/base)
>           scribble/scheme
> -         (for-label racket/generator))
> +         (for-label racket/generator
> +                     racket/mpair))
>
>  @(define generator-eval
>    (lambda ()
> @@ -27,15 +28,21 @@ built-in datatypes, the sequence datatype includes the following:
>
>  @itemize[
>
> + @item{strings (see @secref["strings"])}
> +
> + @item{byte strings (see @secref["bytestrings"])}
> +
>  @item{lists (see @secref["pairs"])}
>
> + @item{mutable lists (see @secref["mpairs"])}
> +
>  @item{vectors (see @secref["vectors"])}
>
>  @item{hash tables (see @secref["hashtables"])}
>
> - @item{strings (see @secref["strings"])}
> + @item{dictionaries (see @secref["dicts"])}
>
> - @item{byte strings (see @secref["bytestrings"])}
> + @item{sets (see @secref["sets"])}
>
>  @item{input ports (see @secref["ports"])}
>
> @@ -63,6 +70,89 @@ each element in the sequence.
>  @defproc[(sequence? [v any/c]) boolean?]{ Return @scheme[#t] if
>  @scheme[v] can be used as a sequence, @scheme[#f] otherwise.}
>
> + at defthing[empty-seqn sequence?]{ A sequence with no elements. }
> +
> + at defproc[(seqn->list [s sequence?]) list?]{ Returns a list whose
> +elements are the elements of the @scheme[s], which must be a one-valued sequence.
> +If @scheme[s] is infinite, this function does not terminate. }
> +
> + at defproc[(seqn-cons [v any/c]
> +                    ...
> +                    [s sequence?])
> +         sequence?]{
> +Returns a sequence whose first element is @scheme[(values v ...)] and whose
> +remaining elements are the same as @scheme[s].
> +}
> +
> + at defproc[(seqn-first [s sequence?])
> +         (values any/c ...)]{
> +Returns the first element of @scheme[s].}
> +
> + at defproc[(seqn-rest [s sequence?])
> +         sequence?]{
> +Returns a sequence equivalent to @scheme[s], except the first element is omitted.}
> +
> + at defproc[(seqn-length [s sequence?])
> +         exact-nonnegative-integer?]{
> +Returns the number of elements of @scheme[s]. If @scheme[s] is infinite, this
> +function does not terminate. }
> +
> + at defproc[(seqn-ref [s sequence?] [i exact-nonnegative-integer?])
> +         (values any/c ...)]{
> +Returns the @scheme[i]th element of @scheme[s].}
> +
> + at defproc[(seqn-tail [s sequence?] [i exact-nonnegative-integer?])
> +         sequence?]{
> +Returns a sequence equivalent to @scheme[s], except the first @scheme[i] elements are omitted.}
> +
> + at defproc[(seqn-append [s sequence?] ...)
> +         sequence?]{
> +Returns a sequence that contains all elements of each sequence in the order they appear in the original sequences. The
> +new sequence is constructed lazily. }
> +
> + at defproc[(seqn-map [f procedure?]
> +                   [s sequence?])
> +         sequence?]{
> +Returns a sequence that contains @scheme[f] applied to each element of @scheme[s]. The new sequence is constructed lazily. }
> +
> + at defproc[(seqn-andmap [f (-> any/c ... boolean?)]
> +                      [s sequence?])
> +         boolean?]{
> +Returns @scheme[#t] if @scheme[f] returns a true result on every element of @scheme[s]. If @scheme[s] is infinite and @scheme[f] never
> +returns a false result, this function does not terminate. }
> +
> + at defproc[(seqn-ormap [f (-> any/c ... boolean?)]
> +                     [s sequence?])
> +         boolean?]{
> +Returns @scheme[#t] if @scheme[f] returns a true result on some element of @scheme[s]. If @scheme[s] is infinite and @scheme[f] never
> +returns a true result, this function does not terminate. }
> +
> + at defproc[(seqn-for-each [f (-> any/c ... any)]
> +                   [s sequence?])
> +         (void)]{
> +Applies @scheme[f] to each element of @scheme[s]. If @scheme[s] is infinite, this function does not terminate. }
> +
> + at defproc[(seqn-fold [f (-> any/c any/c ... any/c)]
> +                    [i any/c]
> +                    [s sequence?])
> +         (void)]{
> +Folds @scheme[f] over each element of @scheme[s] with @scheme[i] as the initial accumulator. If @scheme[s] is infinite, this function does not terminate. }
> +
> + at defproc[(seqn-filter [f (-> any/c ..._0 boolean?)]
> +                      [s sequence?])
> +         sequence?]{
> +Returns a sequence whose elements are the elements of @scheme[s] for which @scheme[f] returns a true result. Although the new sequence is constructed
> +lazily, if @scheme[s] has an infinite number of elements where @scheme[f] returns a false result in between two elements where @scheme[f] returns a true result
> +then operations on this sequence will not terminate during that infinite sub-sequence. }
> +
> + at defproc[(seqn-add-between [s sequence?] [e any/c])
> +         sequence?]{
> +Returns a sequence whose elements are the elements of @scheme[s] except in between each is @scheme[e]. The new sequence is constructed lazily. }
> +
> + at defproc[(seqn-count [s sequence?])
> +         exact-nonnegative-integer?]{
> +Returns the number of elements in @scheme[s]. If @scheme[s] is infinite, this function does not terminate. }
> +
>  @defproc*[([(in-range [end number?]) sequence?]
>            [(in-range [start number?] [end number?] [step number? 1]) sequence?])]{
>  Returns a sequence whose elements are numbers. The single-argument
> @@ -84,6 +174,11 @@ Returns a sequence equivalent to @scheme[lst].
>  @info-on-seq["pairs" "lists"]
>  @speed[in-list "list"]}
>
> + at defproc[(in-mlist [mlst mlist?]) sequence?]{
> +Returns a sequence equivalent to @scheme[mlst].
> + at info-on-seq["mpairs" "mutable lists"]
> + at speed[in-mlist "mutable list"]}
> +
>  @defproc[(in-vector [vec vector?]
>                     [start exact-nonnegative-integer? 0]
>                     [stop (or/c exact-nonnegative-integer? #f) #f]
>
> collects/scribblings/reference/sets.scrbl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/scribblings/reference/sets.scrbl
> +++ NEW/collects/scribblings/reference/sets.scrbl
> @@ -8,14 +8,16 @@ A @deftech{set} represents a set of distinct elements. For a given
>  set, elements are equivalent via @scheme[equal?], @scheme[eqv?], or
>  @scheme[eq?]. Two sets are @scheme[equal?] when they use the same
>  element-comparison procedure (@scheme[equal?], @scheme[eqv?], or
> - at scheme[eq?]) and have equivalent elements. A set can be used as a
> - at tech{sequence} (see @secref["sequences"]).
> + at scheme[eq?]) and have equivalent elements.
> +
> +A set can be used as a single-valued sequence (see
> + at secref["sequences"]). The elements of the set serve as elements
> +of the sequence. See also @scheme[in-set].
>
>  Operations on sets that contain elements that are mutated are
>  unpredictable in much the same way that @tech{hash table} operations are
>  unpredictable when keys are mutated.
>
> -
>  @note-lib[racket/set]
>
>  @defproc[(set? [v any/c]) boolean?]{
>
> collects/scribblings/reference/vectors.scrbl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/scribblings/reference/vectors.scrbl
> +++ NEW/collects/scribblings/reference/vectors.scrbl
> @@ -67,8 +67,7 @@ slot is position @racket[0], and the last slot is one less than
>          void?]{
>
>  Updates the slot @racket[pos] of @racket[vec] to contain @racket[v].}
> -
> -
> +
>  @defproc[(vector->list [vec vector?]) list?]{
>
>  Returns a list with the same length and elements as @racket[vec].}
> @@ -151,6 +150,16 @@ _i)] is the value produced by @racket[(proc _i)].
>  @(interaction-eval #:eval vec-eval
>                    (require racket/vector))
>
> + at defproc[(vector-set*! [vec (and/c vector? (not/c immutable?))]
> +                       [pos exact-nonnegative-integer?]
> +                       [v any/c]
> +                       ...
> +                       ...)
> +         void?]{
> +
> +Updates each slot @racket[pos] of @racket[vec] to contain each @racket[v].
> +The update takes place from the left so later updates overwrite earlier updates.}
> +
>  @defproc[(vector-map [proc procedure?] [vec vector?] ...+)
>          vector?]{
>
>
> collects/tests/racket/basic.rktl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/tests/racket/basic.rktl
> +++ NEW/collects/tests/racket/basic.rktl
> @@ -2363,8 +2363,8 @@
>   (check-all-bad hash-iterate-key)
>   (check-all-bad hash-iterate-value))
>
> -(test (list 1 2 3) hash-domain #hasheq((1 . a)(2 . b)(3 . c)))
> -(test (list 'a 'b 'c) hash-range #hasheq((1 . a)(2 . b)(3 . c)))
> +(test (list 1 2 3) hash-keys #hasheq((1 . a)(2 . b)(3 . c)))
> +(test (list 'a 'b 'c) hash-values #hasheq((1 . a)(2 . b)(3 . c)))
>  (test (list (cons 1 'a) (cons 2 'b) (cons 3 'c)) hash->list #hasheq((1 . a)(2 . b)(3 . c)))
>
>  (err/rt-test (hash-set*! im-t 1 2) exn:fail?)
> @@ -2399,8 +2399,8 @@
>
>  (arity-test make-immutable-hash 1 1)
>  (arity-test make-immutable-hasheq 1 1)
> -(arity-test hash-domain 1 1)
> -(arity-test hash-range 1 1)
> +(arity-test hash-keys 1 1)
> +(arity-test hash-values 1 1)
>  (arity-test hash-count 1 1)
>  (arity-test hash-ref 2 3)
>  (arity-test hash-set! 3 3)
>
> collects/tests/racket/dict.rktl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/tests/racket/dict.rktl
> +++ NEW/collects/tests/racket/dict.rktl
> @@ -12,7 +12,9 @@
>   (test #t dict? d)
>
>   (test 'one dict-ref d 1)
> +  (test #t dict-has-key? d 1)
>   (test 'nope dict-ref d 100 'nope)
> +  (test #f dict-has-key? d 100)
>   (test 'nope dict-ref d 100 (lambda () 'nope))
>
>   (test #t ormap values (dict-map d (lambda (k v) (equal? k orig-one))))
> @@ -23,6 +25,10 @@
>   (test can-remove? dict-can-remove-keys? d)
>   (test can-update? dict-can-functional-set? d)
>
> +  (test (dict-map d cons) 'dict->list (dict->list d))
> +  (test (dict-map d (λ (k v) k)) 'dict-keys (dict-keys d))
> +  (test (dict-map d (λ (k v) v)) 'dict-values (dict-values d))
> +
>   (test (dict-map d cons) 'in-dict
>         (for/list ([(k v) (in-dict d)])
>           (cons k v)))
> @@ -45,7 +51,11 @@
>         (err/rt-test (dict-remove d 1))
>         (err/rt-test (dict-set d 1 "ONE"))
>         (test (void) dict-set! d 1 "ONE")
> -        (test "ONE" dict-ref d 1))
> +        (test "ONE" dict-ref d 1)
> +        (test (void) dict-set*! d 1 (gensym) 1 "TWO")
> +        (err/rt-test (dict-set*! d 1) exn:fail?)
> +        (test "TWO" dict-ref d 1)
> +        (test "TWO" dict-ref! d 1 (gensym)))
>       (let ([cnt (dict-count d)]
>             [smaller (if mutable?
>                          (begin
> @@ -73,10 +83,37 @@
>                        (test #t equal? d bigger)))))])
>           (try-add smaller "ONE")
>           (try-add d "ONE")
> +          (try-add d 'one))
> +        (let ([try-add
> +               (lambda (d val)
> +                 (let ([bigger (if mutable?
> +                                   (begin
> +                                     (err/rt-test (dict-set* smaller 1 val))
> +                                     (dict-set*! smaller 1 (gensym) 1 val)
> +                                     (err/rt-test (dict-set*! smaller 1) exn:fail?)
> +                                     d)
> +                                   (begin
> +                                     (err/rt-test (dict-set*! smaller 1 val))
> +                                     (err/rt-test (dict-set* smaller 1) exn:fail?)
> +                                     (dict-set* smaller 1 (gensym) 1 val)))])
> +                   (test cnt dict-count bigger)
> +                   (when (eq? val 'one)
> +                     (unless (pair? d)
> +                       (test #t equal? d bigger)))))])
> +          (try-add smaller "ONE")
> +          (try-add d "ONE")
>           (try-add d 'one)))))
>
>  (try-simple (vector 'zero 'one 'two) #t #f #f)
>  (try-simple #hash((1 . one) (#f . 7)) #f #t #t)
> +
> +(let ([d (make-hasheq '((1 . one) (#f . 7)))])
> +  (test 'one dict-ref! d 1 (gensym))
> +  (test 'two dict-ref! d 2 'two)
> +  (test 'two dict-ref d 2)
> +  (test 'three dict-ref! d 3 (λ () 'three))
> +  (test 'three dict-ref d 3))
> +
>  (try-simple #hasheq((1 . one) (#f . 7)) #f #t #t)
>  (try-simple (hash-copy #hash((1 . one) (#f . 7))) #t #t #f)
>  (try-simple (hash-copy #hasheq((1 . one) (#f . 7))) #t #t #f)
>
> collects/tests/racket/for.rktl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/tests/racket/for.rktl
> +++ NEW/collects/tests/racket/for.rktl
> @@ -3,7 +3,8 @@
>
>  (Section 'for)
>
> -(require scheme/generator)
> +(require scheme/generator
> +         racket/mpair)
>
>  (define-syntax (test-multi-generator stx)
>   (syntax-case stx ()
> @@ -105,6 +106,8 @@
>
>  (test-generator [(a b c)] '(a b c))
>  (test-generator [(a b c)] (in-list '(a b c)))
> +(test-generator [(a b c)] (mlist 'a 'b 'c))
> +(test-generator [(a b c)] (in-mlist (mlist 'a 'b 'c)))
>  (test-generator [(a b c)] #(a b c))
>  (test-generator [(a b c)] (in-vector #(a b c)))
>  (test-generator [(b c d)] (in-vector #(a b c d) 1))
> @@ -288,4 +291,105 @@
>         (list (maker) (maker) (maker)
>               (maker) (maker) (maker))))
>
> +;; New operators
> +(require racket/private/sequence)
> +
> +(test '(0 1 2) 'seqn->list (seqn->list (in-range 3)))
> +(arity-test seqn->list 1 1)
> +(err/rt-test (seqn->list 1))
> +
> +(test '() 'empty-seqn (seqn->list empty-seqn))
> +
> +; XXX How do I check rest arity?
> +(test '(0 1 2) 'seqn-cons (seqn->list (seqn-cons 0 (in-range 1 3))))
> +(test '((0 1)) 'seqn-cons
> +      (for/list ([(a b) (seqn-cons 0 1 empty-seqn)])
> +        (list a b)))
> +
> +(arity-test seqn-first 1 1)
> +(err/rt-test (seqn-first 1))
> +(test 0 'seqn-first (seqn-first (in-naturals)))
> +(test #t
> +      'seqn-first
> +      (equal? (list 0 1)
> +              (call-with-values
> +               (λ ()
> +                 (seqn-first (seqn-cons 0 1 empty-seqn)))
> +               (λ args args))))
> +
> +(arity-test seqn-rest 1 1)
> +(test '(1 2) 'seqn-rest (seqn->list (seqn-rest (in-range 3))))
> +
> +(arity-test seqn-length 1 1)
> +(err/rt-test (seqn-length 1))
> +(test 3 'seqn-length (seqn-length (in-range 3)))
> +(test 3 'seqn-length (seqn-length #hasheq((1 . 'a) (2 . 'b) (3 . 'c))))
> +
> +(arity-test seqn-ref 2 2)
> +(err/rt-test (seqn-ref 2 0))
> +(err/rt-test (seqn-ref (in-naturals) -1) exn:fail?)
> +(err/rt-test (seqn-ref (in-naturals) 1.0) exn:fail?)
> +(test 0 'seqn-ref (seqn-ref (in-naturals) 0))
> +(test 1 'seqn-ref (seqn-ref (in-naturals) 1))
> +(test 25 'seqn-ref (seqn-ref (in-naturals) 25))
> +
> +(arity-test seqn-tail 2 2)
> +(err/rt-test (seqn-tail (in-naturals) -1) exn:fail?)
> +(err/rt-test (seqn-tail (in-naturals) 1.0) exn:fail?)
> +(test 4 'seqn-ref (seqn-ref (seqn-tail (in-naturals) 4) 0))
> +(test 5 'seqn-ref (seqn-ref (seqn-tail (in-naturals) 4) 1))
> +(test 29 'seqn-ref (seqn-ref (seqn-tail (in-naturals) 4) 25))
> +
> +; XXX Check for rest
> +(err/rt-test (seqn-append 1) exn:fail?)
> +(err/rt-test (seqn-append (in-naturals) 1) exn:fail?)
> +(test '() 'seqn-append (seqn->list (seqn-append)))
> +(test 5 'seqn-append (seqn-ref (seqn-append (in-naturals)) 5))
> +(test 5 'seqn-append (seqn-ref (seqn-append (in-range 3) (in-range 3 10)) 5))
> +
> +(arity-test seqn-map 2 2)
> +(err/rt-test (seqn-map 2 (in-naturals)) exn:fail?)
> +(test '(1 2 3) 'seqn-map (seqn->list (seqn-map add1 (in-range 3))))
> +(test 3 'seqn-map (seqn-ref (seqn-map add1 (in-naturals)) 2))
> +
> +(arity-test seqn-andmap 2 2)
> +(err/rt-test (seqn-andmap 2 (in-naturals)))
> +(test #t 'seqn-andmap (seqn-andmap even? (seqn-cons 2 empty-seqn)))
> +(test #f 'seqn-andmap (seqn-andmap even? (in-naturals)))
> +
> +(arity-test seqn-ormap 2 2)
> +(err/rt-test (seqn-ormap 2 (in-naturals)))
> +(test #t 'seqn-ormap (seqn-ormap even? (seqn-cons 2 empty-seqn)))
> +(test #f 'seqn-ormap (seqn-ormap even? (seqn-cons 1 empty-seqn)))
> +(test #t 'seqn-ormap (seqn-ormap even? (in-naturals)))
> +
> +(arity-test seqn-for-each 2 2)
> +(err/rt-test (seqn-for-each 2 (in-naturals)))
> +(test (vector 0 1 2)
> +      'seqn-for-each
> +      (let ([v (vector #f #f #f)])
> +        (seqn-for-each (λ (i) (vector-set! v i i)) (in-range 3))
> +        v))
> +
> +(arity-test seqn-fold 3 3)
> +(err/rt-test (seqn-fold 2 (in-naturals) 0))
> +(test 6 'seqn-fold (seqn-fold + 0 (in-range 4)))
> +
> +(arity-test seqn-filter 2 2)
> +(err/rt-test (seqn-filter 2 (in-naturals)) exn:fail?)
> +(test 4 'seqn-filter (seqn-ref (seqn-filter even? (in-naturals)) 2))
> +
> +(arity-test seqn-add-between 2 2)
> +(test 0 'seqn-add-between (seqn-ref (seqn-add-between (in-naturals) #t) 0))
> +(test #t 'seqn-add-between (seqn-ref (seqn-add-between (in-naturals) #t) 1))
> +(test 1 'seqn-add-between (seqn-ref (seqn-add-between (in-naturals) #t) 2))
> +(test #t 'seqn-add-between (seqn-ref (seqn-add-between (in-naturals) #t) 3))
> +
> +(arity-test seqn-count 1 1)
> +(test 0 'seqn-count (seqn-count empty-seqn))
> +(test 1 'seqn-count (seqn-count (in-range 1)))
> +(test 10 'seqn-count (seqn-count (in-range 10)))
> +(let ([r (random 100)])
> +  (test r 'seqn-count (seqn-count (in-range r))))
> +
>  (report-errs)
>
> collects/tests/racket/vector.rktl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/tests/racket/vector.rktl
> +++ NEW/collects/tests/racket/vector.rktl
> @@ -24,10 +24,18 @@
>  (err/rt-test (vector-ref #(4 5 6) -1))
>  (err/rt-test (vector-ref #(4 5 6) 2.0))
>  (err/rt-test (vector-ref #(4 5 6) "2"))
> -(test '#(0 ("Sue" "Sue") "Anna") 'vector-set
> +(test '#(0 ("Sue" "Sue") "Anna") 'vector-set!
>        (let ((vec (vector 0 '(2 2 2 2) "Anna")))
>          (vector-set! vec 1 '("Sue" "Sue"))
>          vec))
> +(test '#(0 1 2) 'vector-set*!
> +      (let ([vec (vector #f #f #f)])
> +        (vector-set*! vec
> +                      0 (gensym) 0 0
> +                      1 (gensym) 1 1
> +                      2 (gensym) 2 2)
> +        vec))
> +
>  (test '#(hi hi) make-vector 2 'hi)
>  (test '#() make-vector 0)
>  (test '#() make-vector 0 'a)
> @@ -39,6 +47,7 @@
>  (err/rt-test (make-vector -1 'a))
>  (err/rt-test (make-vector 1000000000000000000000 'a) exn:fail:out-of-memory?)
>  (arity-test vector-set! 3 3)
> +(err/rt-test (vector-set*! #() 0 'x 1) exn:fail?)
>  (err/rt-test (vector-set! #() 0 'x) exn:application:mismatch?)
>  (err/rt-test (vector-set! #(1 2 3) -1 'x))
>  (err/rt-test (vector-set! #(1 2 3) 3 'x) exn:application:mismatch?)
>
> collects/tests/unstable/dict.rkt
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/tests/unstable/dict.rkt
> +++ NEW/collects/tests/unstable/dict.rkt
> @@ -35,13 +35,6 @@
>                (dict-set! table 2 'b)
>                (check/dict table '([1 . a] [2 . b]))))))
>    (test-suite "Lookup"
> -     (test-suite "dict-ref!"
> -       (test-ok (define d (make-hash))
> -                (check-equal? (dict-ref! d 1 'one) 'one)
> -                (check-equal? (dict-ref! d 1 'uno) 'one)
> -                (check-equal? (dict-ref! d 2 (lambda () 'two)) 'two)
> -                (check-equal? (dict-ref! d 2 (lambda () 'dos)) 'two))
> -       (test-bad (dict-ref! '([1 . one] [2 . two]) 1 'uno)))
>      (test-suite "dict-ref/check"
>        (test-ok (check-equal? (dict-ref/check '([1 . one] [2 . two]) 1) 'one))
>        (test-bad (dict-ref/check '([1 . one] [2 . two]) 3)))
> @@ -65,15 +58,7 @@
>    (test-suite "Accessors"
>      (test-suite "dict-empty?"
>        (test (check-true (dict-empty? '())))
> -       (test (check-false (dict-empty? '([1 . a] [2 . b])))))
> -     (test-suite "dict-has-key?"
> -       (test-ok (check-equal? (dict-has-key? '([1 . one] [2 . two]) 1) #t))
> -       (test-ok (check-equal? (dict-has-key? '([1 . one] [2 . two]) 3) #f)))
> -     (test-suite "dict-domain"
> -       (test-ok (check-equal? (dict-domain '([1 . one] [2 . two])) '(1 2))))
> -     (test-suite "dict-range"
> -       (test-ok (check-equal? (dict-range '([1 . one] [2 . two]))
> -                              '(one two)))))
> +       (test (check-false (dict-empty? '([1 . a] [2 . b]))))))
>    (test-suite "Combination"
>      (test-suite "dict-union"
>        (test-ok (dict-union '([1 . one] [2 . two]) '([3 . three] [4 . four]))
>
> collects/unstable/dict.rkt
> ~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/unstable/dict.rkt
> +++ NEW/collects/unstable/dict.rkt
> @@ -8,35 +8,6 @@
>  ;;
>  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> -(define dict-has-key?
> -  (let ()
> -    (with-contract
> -     dict-has-key?
> -     ([dict-has-key? (-> dict? any/c boolean?)])
> -     (define (dict-has-key? dict key)
> -       (let/ec return
> -         (dict-ref dict key (lambda () (return #f)))
> -         #t)))
> -    dict-has-key?))
> -;; Ryan: Why the with-contract region? Why not provide/contract?
> -
> -(define dict-ref!
> -  (let ()
> -    (with-contract
> -     dict-ref!
> -     ([dict-ref! (-> (and/c dict? dict-mutable?)
> -                     any/c
> -                     (or/c (-> any/c) any/c)
> -                     any/c)])
> -     (define (dict-ref! dict key failure)
> -       (dict-ref
> -        dict key
> -        (lambda ()
> -          (let* ([value (if (procedure? failure) (failure) failure)])
> -            (dict-set! dict key value)
> -            value)))))
> -    dict-ref!))
> -
>  (define (dict-empty? dict)
>   (= (dict-count dict) 0))
>
> @@ -105,18 +76,6 @@
>
>  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>  ;;
> -;;  Extra Accessors
> -;;
> -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> -
> -(define (dict-domain dict)
> -  (for/list ([i (in-dict-keys dict)]) i))
> -
> -(define (dict-range dict)
> -  (for/list ([i (in-dict-values dict)]) i))
> -
> -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> -;;
>  ;;  Union
>  ;;
>  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> @@ -231,7 +190,7 @@
>  ;;
>  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> -(provide dict/c dict-has-key? dict-ref!)
> +(provide dict/c)
>  (provide/contract
>  [dict-empty? (-> dict? boolean?)]
>  [empty-dict
> @@ -262,8 +221,6 @@
>   (->d ([table dict?] [key any/c]) ()
>        #:pre-cond (dict-has-key? table key)
>        [_ any/c])]
> - [dict-domain (-> dict? list?)]
> - [dict-range (-> dict? list?)]
>  [dict-union (->* [(and/c dict? dict-can-functional-set?)]
>                   [#:combine
>                    (-> any/c any/c any/c)
>
> collects/unstable/scribblings/dict.scrbl
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> --- OLD/collects/unstable/scribblings/dict.scrbl
> +++ NEW/collects/unstable/scribblings/dict.scrbl
> @@ -72,32 +72,6 @@ and is thus essentially equivalent to a list-based dictionary.
>
>  @section{Dictionary Lookup}
>
> - at defproc[(dict-ref! [d (and/c dict? dict-mutable?)]
> -                    [k any/c]
> -                    [v (or/c (-> any/c) any/c)])
> -         any/c]{
> -
> -Looks up key @scheme[k] in dictionary @scheme[d].  If @scheme[d] has no entry
> -for @scheme[k], updates @scheme[d] to map @scheme[k] to the result of
> - at scheme[(v)] (if @scheme[v] is a procedure) or @scheme[v] (otherwise), and
> -returns the new mapping.
> -
> - at defexamples[
> -#:eval (eval/require 'racket/dict 'unstable/dict)
> -(define d (make-hash))
> -(dict-set! d 1 'one)
> -(dict-set! d 2 'two)
> -d
> -(dict-ref! d 2 'dos)
> -d
> -(dict-ref! d 3 'tres)
> -d
> -(dict-ref! d 4 gensym)
> -d
> -]
> -
> -}
> -
>  @defproc[(dict-ref/check [d dict?] [k (lambda (k) (dict-has-key? d k))])
>          any/c]{
>
> @@ -168,40 +142,6 @@ Reports whether @scheme[d] is empty (has no keys).
>
>  }
>
> - at defproc[(dict-has-key? [d dict?] [k any/c]) boolean?]{
> -
> -Reports whether @scheme[d] has an entry for @scheme[k].
> -
> - at defexamples[
> -#:eval (eval/require 'racket/dict 'unstable/dict)
> -(dict-has-key? '([1 . one] [2 . two] [3 . three]) 2)
> -(dict-has-key? '([1 . one] [2 . two] [3 . three]) 4)
> -]
> -
> -}
> -
> - at defproc[(dict-domain [d dict?]) list?]{
> -
> -Produces the domain of a dictionary as a list of keys.
> -
> - at defexamples[
> -#:eval (eval/require 'racket/dict 'unstable/dict)
> -(dict-domain '([1 . one] [2 . two] [3 . three]))
> -]
> -
> -}
> -
> - at defproc[(dict-range [d dict?]) list?]{
> -
> -Produces the range of a dictionary as a list of values.
> -
> - at defexamples[
> -#:eval (eval/require 'racket/dict 'unstable/dict)
> -(dict-range '([1 . one] [2 . two] [3 . three]))
> -]
> -
> -}
> -
>  @section{Dictionary Combinations}
>
>  @defproc[(dict-union [d0 (and/c dict? dict-can-functional-set?)]
>



-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://teammccarthy.org/jay

"The glory of God is Intelligence" - D&C 93


Posted on the dev mailing list.