[racket users] Generics question

33 views
Skip to first unread message

Kevin Forchione

unread,
Mar 3, 2020, 11:08:08 AM3/3/20
to Racket-Users List
Hi guys,
If I create a generic, say foo, for a particular struct and then later reference that method on a different type of struct from within the handler method I get an error because the call goes to the original structs method and not to the method of the other struct. Is there a way to do this?

Here’s a very artificial example:

#lang racket

(require racket/generic)

(define-generics foo
[do-foo foo])

(struct A (this other) #:transparent
#:methods gen:foo
[(define (do-foo foo)
(printf "other=~a ~a"
(A-this foo)
(do-foo (A-other foo))))])
(struct B (lst) #:transparent
#:methods gen:foo
[(define (do-foo foo)
(printf "lst=~a"
(B-lst foo)))])

(define b (B '(x y z)))
(define a (A 'a b))

(do-foo b) ;=> lst=(x y z)

(do-foo a) ;=> A-this: contract violation
expected: A?
given: (B '(x y z))

Thanks,
Kevin

Jon Zeppieri

unread,
Mar 3, 2020, 11:19:25 AM3/3/20
to Kevin Forchione, Racket-Users List
Kevin,

This is what `define/generic` is for. In your example:

On Tue, Mar 3, 2020 at 11:08 AM Kevin Forchione <lys...@gmail.com> wrote:
>
> (struct A (this other) #:transparent
> #:methods gen:foo
> [(define (do-foo foo)
> (printf "other=~a ~a"
> (A-this foo)
> (do-foo (A-other foo))))])

The call to `(doo-foo (A-other foo))` is simply a recursive call to
the function that you're in the middle of defining. In order to call
the generic method and have it dispatched appropriately, you need to
use `define/generic`:

(struct A (this other) #:transparent
#:methods gen:foo
[(define/generic generic-foo do-foo)
(define (do-foo foo)
(printf "other=~a ~a"
(A-this foo)
(generic-foo (A-other foo))))])

- Jon

Kevin Forchione

unread,
Mar 3, 2020, 12:37:13 PM3/3/20
to Jon Zeppieri, Racket-Users List
On Mar 3, 2020, at 9:19 AM, Jon Zeppieri <zepp...@gmail.com> wrote:

(struct A (this other) #:transparent
 #:methods gen:foo
 [(define/generic generic-foo do-foo)
  (define (do-foo foo)
    (printf "other=~a ~a"
            (A-this foo)
            (generic-foo (A-other foo))))])

Thanks!  That brings me a little closer in appreciating the comments I’ve read about replacing object-oriented code with structs and methods. 

Is this part of the racket/generic or the Multimethods library? The example you provide works from racket/generic, but the search in docs pulls up only the multimethod docs and the examples don’t work from racket/generic. 

Kevin

Jon Zeppieri

unread,
Mar 3, 2020, 12:48:16 PM3/3/20
to Kevin Forchione, Racket-Users List
On Tue, Mar 3, 2020 at 12:37 PM Kevin Forchione <lys...@gmail.com> wrote:
>
> Thanks! That brings me a little closer in appreciating the comments I’ve read about replacing object-oriented code with structs and methods.
>
> Is this part of the racket/generic or the Multimethods library? The example you provide works from racket/generic, but the search in docs pulls up only the multimethod docs and the examples don’t work from racket/generic.
>
> Kevin

It's in racket/generic. Here's a link to the documentation for
`define/generic`:
https://docs.racket-lang.org/reference/struct-generics.html?q=define%2Fgeneric#%28form._%28%28lib._racket%2Fgeneric..rkt%29._define%2Fgeneric%29%29

- Jon

Kevin Forchione

unread,
Mar 3, 2020, 1:09:05 PM3/3/20
to Jon Zeppieri, Racket-Users List
Oh, I see. I searched for “define-generic” instead of “define/generic”! Well, that explains my confusion and opens up more options as well. :)

Kevin
Reply all
Reply to author
Forward
0 new messages