
Hello there! When I try this kind of module architecture, I get struct-out: multiple bindings (set-container-elements!, set-container-elements!, ...) for structure-type identifier

Is this a bug in struct-out
or am I doing something wrong?

it was working fine until I made elements
mutable

@jesus Well first I get an error on the (require 'private)
because the foo
module is a sibling that can’t see the private
module. I’m guessing these modules were originally files like "private.rkt"
, "foo.rkt"
and so on? But assuming they are split into files like that: I can’t explain the behavior you’re seeing. I can say what I would do instead is: ;; private.rkt
#lang racket/base
(provide (struct-out element)
(struct-out container))
(struct element (name value) #:transparent)
(struct container element ([elements #:mutable]) #:transparent)
;; foo.rkt -- and likewise for bar.rkt and baz.rkt
#lang racket/base
(require "private.rkt")
(provide (except-out (struct-out foo) foo)
(rename-out [-foo foo]))
(struct foo container ())
(define (-foo)
(foo "Foo" 0 '()))
;; public.rkt
#lang racket/base
(require "foo.rkt" "bar.rkt" "baz.rkt")
(provide (all-from-out "foo.rkt")
(all-from-out "bar.rkt")
(all-from-out "baz.rkt"))
;; user.rkt
#lang racket/base
(require "public.rkt")
(define my-foo (foo))
(set-container-elements! my-foo (list (bar) (baz)))
(displayln my-foo)

TL;DR Instead of using #:name
, just define the “special constructor” as a plain function and rename it on provide. Omit the “normal” ctor from the struct-out
.

Also I kind of prefer public.rkt
this way, because it simply re-provides foo.rkt
et al as-is. (In fact it’d be trivial using #lang reprovide
.)

But yes. I agree it’s weird if your original way stopped working just because you added #:mutable
. If that’s really your question, I have no answer. Someone else hopefully does.

Arg. Maybe I should @
the correct person. @jerome.martin.dev ^