1
votes

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.

2

2 Answers

2
votes

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.

.

1
votes

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 ...)))) ...))))))