Dispatching generic defaults on struct type

Hi, I'd like to make a generic interface as such:

#lang racket                                                                                                                             
                                                                                                                                         
(require racket/generic)                                                                                                                 
                                                                                                                                         
(define-generics interfaceable                                                                                                           
  (a interfaceable)                                                                                                                      
  (b interfaceable)                                                                                                                      
  #:defaults ([dummy-struct?                                                                                                             
               (define (b itfc) "I'm a default generic!")]))                                                                             
                                                                                                                                         
(struct dummy-struct ()                                                                                                                  
  #:methods gen:interfaceable                                                                                                            
  [(define (a self) "I apply to my own type!")])

I'd like to dispatch the defaults according to struct type, but this results in:

; dummy-struct?: undefined;                                                                                                              
;  cannot reference an identifier before its definition                                                                                  
;   in module: "/home/raoul/Desktop/sqldf/scratch.rkt"

Is there a way around that with generics? Thanks!

1 Like

The problem is that dummy-struct? is not defined yet when the reference in the generics definition is evaluated. Swapping the order won't work, because the struct definition depends on the generics definition.

The general solution to this sort of problem is to delay the evaluation of the reference by wrapping it in a lambda expression that just calls the same function. (This is sometimes called "eta expansion".)

In this case, replace dummy-struct? with (lambda (v) (dummy-struct? v)).

1 Like

Thanks, this indeed makes the syntax error disappear, but now:

scratch.rkt> (define ds (dummy-struct))                                                                                                  
scratch.rkt> (a ds)                                                                                                                      
"I apply to my own type!"                                                                                                                
scratch.rkt> (b ds)                                                                                                                      
; b: not implemented for #<dummy-struct>                                                                                                 
; Context (plain; to see better errortrace context, re-run with C-u prefix):                                                             
;   /usr/share/racket/collects/racket/private/generic.rkt:485:0 body of "/home/raoul/Desktop/sqldf/scratch.rkt"

So, it seems dispatch fails nevertheless. Which I don't understand since the predicate now works...

Oh, right. I think the implementation associated with the struct type simply overrides the implementation from the #:defaults clause. They don't get merged. To do that, use #:fallbacks instead.