[racket] struct generics and mutual dependencies

From: Jon Zeppieri (zeppieri at gmail.com)
Date: Wed Aug 20 15:19:39 EDT 2014

Thanks, Vincent. I'll go with that. -J

On Wed, Aug 20, 2014 at 3:00 PM, Vincent St-Amour <stamourv at ccs.neu.edu> wrote:
> We added these options to allow retrofitting methods on already defined
> types. We've used it to break cyclic dependencies inside the standard
> library, so I'd say it's the right way to do what you're trying to do.
>
> Vincent
>
>
> At Tue, 19 Aug 2014 01:29:39 -0400,
> Jon Zeppieri wrote:
>>
>> 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
>> ____________________
>>   Racket Users list:
>>   http://lists.racket-lang.org/users

Posted on the users mailing list.