How to `dynamic-require` from the enclosing module?

I'm trying to obtain a function from a symbol within a submodule, something like:

# lang racket

(define (foo x) (list x))

(module+ my-mod
  (dynamic-require <something> 'foo))

This can be done with some syntax magic (with syntax/location) and <something> = (list 'file <file-path-string>), but there must be a proper, simpler and likely more robust way.

I also tried namespace-variable-value but while it works within DrRacket it doesn't work on the command line — or I did it wrong.

I recommend (quote-module-path "..") using syntax/location.

The primitive form would be (module-path-index-join '(submod "..") (variable-reference->module-path-index (#%variable-reference))), and that's roughly what quote-module-path expands to.

2 Likes

I see. So, IIUC, once encapsulated in a library, this still requires passing a syntax object from the actual submodule to the library so as to know the source location, is that correct?

I would use define-runtime-module-path-index from racket/runtime-path, which also registers a dynamic dependency for tools like raco exe:

#lang racket

(define (foo x)
  (list x))

(provide foo)

(module+ main
  (require racket/runtime-path)
  (define-runtime-module-path-index foo-mpi
    '(submod ".."))
  (dynamic-require foo-mpi 'foo))

My concern about this is that the docs say the result will only be a valid module path “when possible”. Since the docs say it “builds the result using quote, a path, submod, or 'top-level”, I thought it had limitations with some kinds of module paths, at least unsaved modules in DrRacket.

1 Like