Re: Record types checking
Daphne Preston-Kendal 22 Sep 2024 10:44 UTC
Don’t use set! in the implementation to replace the original definitions. This will mark the bindings as mutable and cause a performance hit. Generate a number of temporaries to be the names auto-defined by (scheme base)’s `define-record-type`, then `define-record-type-checked` defines the ‘correct’ names wrapping the originals. If you don’t know how to generate arbitrary numbers of temporaries in syntax-rules, see <https://gitlab.com/dpk/presrfis/-/blob/master/call.scm> which is a pedagogical example I wrote of the standard technique.
By the way, you don’t need to check on the accessors. Since the constructor and the mutator both check the type on the way in, it doesn’t to be checked again on the way out. (On Schemes with a record inspection layer someone could go in through the back door and change fields to values with the wrong type. But this is a problem that would need to be solved at the lower level within the record type system. (Have I mentioned recently I hate record types? All the features are interconnected with one another in these annoying ways that makes it hard for new features to compose with one another.))
Daphne
> On 22 Sep 2024, at 08:36, Antero Mejr (via srfi-253 list) <xxxxxx@srfi.schemers.org> wrote:
>
> Would it be helpful to add a define-record-type-checked macro? Since
> define-record-type can generate many procedures, it could be tedious to
> wrap each of them with checked versions.
>
> Here is a (mostly) portable R7RS implementation built on
> define-record-type:
> ```
> (cond-expand
> (gauche) ; Does not work in Gauche due to inlining.
> (else
> (define-syntax set!-record-field-checked
> (syntax-rules ()
> ((_ predicate check)
> (begin))
> ((_ predicate check mutator)
> (let ((x mutator))
> (set! mutator (lambda-checked ((obj predicate) (val check))
> (x obj val)))))))
> (define-syntax accessor-checked
> (syntax-rules ()
> ((_ predicate accessor)
> (let ((x accessor))
> (set! accessor (lambda-checked ((obj predicate))
> (x obj)))))))
> (define-syntax define-record-type-checked
> (syntax-rules ()
> ((_ type
> (constructor (tag check) ...)
> predicate
> (field-tag accessor . more) ...)
> (begin (define-record-type type
> (new-constructor tag ...)
> predicate
> (field-tag accessor . more) ...)
> (define-checked (constructor (tag check) ...)
> (new-constructor tag ...))
> (accessor-checked predicate accessor) ...
> (set!-record-field-checked predicate check . more)
> ...))))))
> ```