diff --git a/pkgs/racket-doc/scribblings/reference/pairs.scrbl b/pkgs/racket-doc/scribblings/reference/pairs.scrbl index fdc6e24f5a..57802e33b2 100644 --- a/pkgs/racket-doc/scribblings/reference/pairs.scrbl +++ b/pkgs/racket-doc/scribblings/reference/pairs.scrbl @@ -866,6 +866,27 @@ Returns a newly constructed list of length @racket[k], holding @mz-examples[#:eval list-eval (make-list 7 'foo)]} +@defproc[(list-update [lst list?] + [pos (and/c (>=/c 0) ( any/c any/c)]) + list?]{ + +Returns a list that is the same as @racket[lst] except at the specified index. +The element at the specified index is @racket[(updater (list-ref lst pos))]. + +@examples[#:eval list-eval +(list-update '(zero one two) 1 symbol->string)]} + +@defproc[(list-set [lst list?] + [pos (and/c (>=/c 0) (string) +(test '(zero "one" two) list-update '(zero one two) 1 symbol->string) +(err/rt-test (list-update '(zero one two) 3 symbol->string)) +(err/rt-test (list-update '(zero one two) -1 symbol->string)) +(err/rt-test (list-update '(zero one two) #f symbol->string)) +(err/rt-test (list-update #f 0 symbol->string)) +(err/rt-test (list-update '(zero one two) 0 #f)) + +;; ---------- list-set ---------- + +(test '(zero one "two") list-set '(zero one two) 2 "two") +(err/rt-test (list-set '(zero one two) 3 "two")) +(err/rt-test (list-set '(zero one two) -1 "two")) +(err/rt-test (list-set '(zero one two) #f "two")) + (report-errs) diff --git a/racket/collects/racket/list.rkt b/racket/collects/racket/list.rkt index 838d64a9a3..c23a30db89 100644 --- a/racket/collects/racket/list.rkt +++ b/racket/collects/racket/list.rkt @@ -10,6 +10,9 @@ make-list + list-update + list-set + drop take split-at @@ -102,6 +105,25 @@ (let loop ([n n] [r '()]) (if (zero? n) r (loop (sub1 n) (cons x r))))) +(define (list-update l i f) + (unless (list? l) + (raise-argument-error 'list-update "list?" l)) + (unless (exact-nonnegative-integer? i) + (raise-argument-error 'list-update "exact-nonnegative-integer?" i)) + (unless (and (procedure? f) + (procedure-arity-includes? f 1)) + (raise-argument-error 'list-update "(-> any/c any/c)" f)) + (cond + [(zero? i) (cons (f (car l)) (cdr l))] + [else (cons (car l) (list-update (cdr l) (sub1 i) f))])) + +(define (list-set l k v) + (unless (list? l) + (raise-argument-error 'list-update "list?" l)) + (unless (exact-nonnegative-integer? k) + (raise-argument-error 'list-update "exact-nonnegative-integer?" k)) + (list-update l k (lambda (_) v))) + ;; internal use below (define (drop* list n) ; no error checking, returns #f if index is too large (if (zero? n) list (and (pair? list) (drop* (cdr list) (sub1 n)))))