Traits and interfaces

I’m tying to work with traits and I discovered that traits can’t implement interfaces, so I can’t use the is-a? predicate.

There’s a solution to this problem: create an empty mixin that adds only the interface definition.

Here’s an example:

(require racket/trait)

(define simple-int (interface () method1))

(define simple% (class* object% ()

(define simple-trait (trait
                       (define/public (method1) 0)))

(define simple-class% ((trait->mixin simple-trait) simple%))

(define simple-mixin/int (mixin () (simple-int)

(define new-class% (simple-mixin/int simple-class%))
(define new-object (new new-class%))

(is-a? new-object simple-int) => #t

I tried to write this macro, but it doesn’t work.

(define-syntax trait->mixin*
  (syntax-rules ()
    [((trait->mixin* T (interface-exp …)) C)
       (define mixin/int (mixin () (interface-exp …)
       (mixin/int ((trait->mixin T) C)))]))

What do you think?


The macro doesn't work because it is trying to match a pattern like:

((identifier stuff ...) stuff ...)

The Racket macro expander only works with patterns that are either identifier or (more commonly):

(identifier stuff ...)

A working trait->mixin* would be something like:

(define-syntax trait->mixin*
  (syntax-rules ()
    [(trait->mixin* T (I* ...))
     (let ([T-mixin (trait->mixin T)]
           [I-mixin (mixin () (I* ...) (super-new))])
       (λ (%)
         (I-mixin (T-mixin %))))]))
1 Like