Getting all available submodules in a module

I have a module wherein I defined several submodules. Is there an easy way to get a list of all of the submodules? If I have the following file, example.rkt

#lang racket/base

(module one racket/base
  (provide doc)
  (define doc "Hello from here."))

(module two racket/base
  (provide doc)
  (define doc "Hello from here, too."))

Then I can dynamic-require the submodules individually with (dynamic-require '(submod "example1.rkt" one) 'doc). What I would like to do is essentially be able to map over all submodules, requiring a variable that is known to be defined (would be even better if I can somehow test if it actually is defined).

I feel like there should be a somewhat elegant solution, but I haven't found anything in that direction

A bit of a hack?

Bind a runtime variable to the (compile-time) result of syntax-local-submodules, then use the failure-thunk for when the binding you want isn't available.

Though I doubt this will cooperate well with raco exe/dist/demod, so if you plan to use those you might end up needing to maintain a static list of "dynamically required submodules" anyway.

1 Like

Needs some dynamic requiring here :smiley:

Moreover, I think in this code SRC.rkt can't be already compiled (to .zo).

#lang racket/base

(define old-compile (current-compile))

(define compiled-mod #f)

(parameterize ([current-compile (lambda (form imm-use?)
                                  (define compiled-res (old-compile form imm-use?))
                                  (define name (current-module-declare-name))
                                  (when (and (resolved-module-path? name)
                                             (regexp-match? #rx"SRC[.]rkt"
                                                            (path->string
                                                             (resolved-module-path-name
                                                              name))))
                                    (set! compiled-mod compiled-res))
                                  compiled-res)])
  (dynamic-require "SRC.rkt" #f))

'module
(map module-compiled-name (module-compiled-submodules compiled-mod #f))

'module*
(map module-compiled-name (module-compiled-submodules compiled-mod #t))

Cool, that looks pretty good! One surprising thing is that this also lists a submodule with the name configure-runtime in the modules. I actually don't know where that is coming from, it's a bit surprising to me to see it show up. Though I guess that should be reasonably easy to filter out.

(And a really small nitpick: the order of 'module and 'module* is swapped.)

configure-runtime is added by #lang racket[/base] 3.1 Modules: module, module*, ....