Scheme Parent Protocols

Here’s a subtle point of using Scheme (Chez, R6RS) records with inheritance:

;; creates a record, two default fields
(define-record-type Foo
    (fields (mutable x) (mutable y))
    (protocol (λ (new) (λ ()
        (new 1 2) )))
)

;; creates a subtype, one specified field
(define-record-type Bar
    (parent Foo)
    (fields (mutable z))
    (protocol (λ (super-new) (λ (z)
        (let [ (new (super-new)) ]
            (new z) ))))
)

(define b (make-Bar 3))
(Foo-x b)
1
(Foo-y b)
2
(Bar-z b)
3

The “new” your subtype protocol (constructor, in any OOP system) gets is a wrapper function that calls the parent protocol, and returns your actual “new”. If you don’t have a protocol, you just do (make-Bar 1 2 3) and that works.

It’s a little annoying that define-record-type doesn’t copy accessors forward, leading to either that mess of Foo-x/y, Bar-z, or a long list of (define Bar-x Foo-x) etc., but if I wanted a real object system I already have one. In my use case records are faster, I just didn’t understand this quirk, and the docs don’t help by calling the constructors “n” and “p”.