I have searched the Chez Scheme documentation for an answer to this question but can't seem to find it:
Does Chez have a functional copy/update for its Records - something like Racket has for its Structures?
Thank you.
I have searched the Chez Scheme documentation for an answer to this question but can't seem to find it:
Does Chez have a functional copy/update for its Records - something like Racket has for its Structures?
Thank you.
Records with support for functional updates are specified in SRFI 57. An implementation is provided by its original author, André van Tonder, as a portable R7RS library. Simple wrappers that can accommodate R7RS in Chez, which embraces R6RS, are available in the wild, but I will recommend a comprehensive system that does an excellent job of "vigorously shaking code it until it behaves properly", namely Akku.scm.
.
I recently wrote a macro called define-immutable-record
which produces an immutable record type along with procedures named like this: record-with-field
which return updated copies of the record. Here it is:
;; Synthesises a symbol from strings and syntax objects
(meta define (synth-symbol . parts)
(define (part->string x)
(if (string? x) x (symbol->string (syntax->datum x))))
(string->symbol (apply string-append (map arg->string parts))))
;; Synthesises an identifier for use in an unhygenic macro
(meta define (gen-id template-id . parts)
(datum->syntax template-id (apply synth-symbol parts)))
;; Defines a record with all fields being immutable. Also defines
;; functions of the form `record-with-field`, e.g:
;;
;; (define-immutable-record point (x 0) (y 1))
;; (make-point) => (point (x 0) (y 1))
;; (make-point 3) => (point (x 3) (y 1))
;; (point-with-x (make-point 3 4) 99) => (point (x 99) (y 4))
(define-syntax define-immutable-record
(lambda (x)
(define (gen-ids k record-name conj-str fields)
(dat->syn k (map (lambda (f) (synth-symbol record-name conj-str f))
(syn->dat fields))))
(syntax-case x ()
((k record-name field ...)
(with-syntax ((make-fn (gen-id #'k "make-" #'record-name))
((with-fn ...) (gen-ids #'k #'record-name "-with-" #'(field ...)))
((get-fn ...) (gen-ids #'k #'record-name "-" #'(field ...))))
#'(begin
(define-record-type record-name
(fields (immutable field) ...))
(define (with-fn record new-value)
(let ([field (get-fn record)] ...)
(let ([field new-value])
(make-fn field ...)))) ...))))))