[racket] struct generics and mutual dependencies
I think you can also do it with lazy-require:
#lang racket/base
(module generics racket/base
(provide (all-defined-out))
(require racket/generic)
(define-generics ->foo-provider
(->foo ->foo-provider))
(define-generics ->bar-provider
(->bar ->bar-provider)))
(module foo racket/base
(provide (struct-out foo))
(require racket/lazy-require
(submod ".." generics))
(lazy-require
[(submod ".." bar) (bar)])
(struct foo (x)
#:methods gen:->foo-provider
[(define (->foo f) f)]
#:methods gen:->bar-provider
[(define (->bar f) (bar (foo-x f)))]))
(module bar racket/base
(provide (struct-out bar))
(require (submod ".." generics)
(submod ".." foo))
(struct bar (x)
#:methods gen:->foo-provider
[(define (->foo b) (foo (bar-x b)))]
#:methods gen:->bar-provider
[(define (->bar b) b)]))
(module+ test
(require rackunit)
(require (submod ".." generics)
(submod ".." foo)
(submod ".." bar))
(check-equal? (foo-x (->foo (bar 1))) 1)
(check-equal? (bar-x (->bar (foo 1))) 1))
On 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140820/ff7321ab/attachment.html>