[racket] struct generics and mutual dependencies

From: Jon Zeppieri (zeppieri at gmail.com)
Date: Tue Aug 19 01:29:39 EDT 2014

I do see another option. I could use either the #:defaults or
#fast-defaults options to define-generics to separate the struct type
definitions from the methods. I'm not sure if this is a legitimate use
of the feature or an abuse. -J

On Mon, Aug 18, 2014 at 11:44 PM, Jon Zeppieri <zeppieri at gmail.com> wrote:
> Say I want to do basically the following, except with larger, more
> complicated generic interfaces:
> ```racket
> #lang racket/base
> (require racket/generic)
> (define-generics ->foo-provider
>   (->foo ->foo-provider))
> (define-generics ->bar-provider
>   (->bar ->bar-provider))
> (struct foo (x)
>   #:methods gen:->foo-provider
>   [(define (->foo f) f)]
>   #:methods gen:->bar-provider
>   [(define (->bar f) (bar (foo-x f)))])
> (struct bar (x)
>   #:methods gen:->foo-provider
>   [(define (->foo b) (foo (bar-x b)))]
>   #:methods gen:->bar-provider
>   [(define (->bar b) b)])
> ```
> That is, I want to have struct types that can use generic methods to
> construct instances of one another. Since the actual struct types are
> rather more complicated than this example, I'd really like to split up
> their implementations into separate modules. If I weren't using
> generics, this would be straightforward; I'd put the struct type
> definitions themselves in a module, or set of modules, and I'd put the
> operations in modules specific to their respective struct types. The
> modules containing the operations would be able to require all of the
> struct type definitions, so they could freely construct instances of
> one another.
> In the present case, however, the method implementations need to be
> defined along with the struct type definition. I can't do something
> like:
> ```
> [(define ->foo bar->foo)]
> ```
> ... where bar->foo comes from a bar-specific module, because that
> would lead to a circular dependency (bar->foo needs the foo
> constructor, which is defined in this module, while this module needs
> bar->foo).
> I could work around this with mutable bindings (either at the module
> level or, better, in method dispatch), but I'm not fond of either
> approach. With the right structure inspector maybe (?) it would be
> possible to modify whatever dispatch table is actually used, but that
> sounds hairy. I guess I'm wondering if some other trick is possible
> here.
> -Jon

Posted on the users mailing list.