[racket] struct generics and mutual dependencies

From: Alexander D. Knauth (alexander at knauth.org)
Date: Wed Aug 20 13:27:52 EDT 2014

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))
   [(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>

Posted on the users mailing list.