diff --git a/collects/racket/dict.rkt b/collects/racket/dict.rkt index 19a4359e4d..862276229c 100644 --- a/collects/racket/dict.rkt +++ b/collects/racket/dict.rkt @@ -10,6 +10,7 @@ dict-can-functional-set? dict-ref + dict-ref! dict-set! dict-set*! dict-set @@ -230,6 +231,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)] diff --git a/collects/scribblings/reference/dicts.scrbl b/collects/scribblings/reference/dicts.scrbl index 49535a35d2..a488ad0663 100644 --- a/collects/scribblings/reference/dicts.scrbl +++ b/collects/scribblings/reference/dicts.scrbl @@ -212,7 +212,27 @@ result: (dict-ref #("apple" "banana") -3 #f) ]} +@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 +@scheme[key]. (Note that if @scheme[to-set] is a thunk, it is not +invoked in tail position.) + +@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] diff --git a/collects/tests/racket/dict.rktl b/collects/tests/racket/dict.rktl index 19fcdd1f90..a449ca8047 100644 --- a/collects/tests/racket/dict.rktl +++ b/collects/tests/racket/dict.rktl @@ -49,7 +49,10 @@ (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") + (test "TWO" dict-ref d 1) + (test "TWO" dict-ref! d 1 (gensym))) (let ([cnt (dict-count d)] [smaller (if mutable? (begin @@ -98,6 +101,14 @@ (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)