# Providing name only to sub-module?

**URL:** <https://racket.discourse.group/t/providing-name-only-to-sub-module/3918>\
**Category:** Questions & Answers\
**Tags:** macro, testing\
**Created:** [August 24, 2025, 3:32am UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918 "2025-08-24T03:32:38Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![pcn](https://avatars.discourse-cdn.com/v4/letter/p/65b543/32.png) [@pcn](https://racket.discourse.group/u/pcn)\
**Post date:** [August 24, 2025, 3:32am UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/1 "2025-08-24T03:32:38Z")

</div>

Context: Inspired by Lean's `#guard` commands, I'd like to implement ["static unit tests"](https://github.com/philnguyen/examples) in Racket, where tests give the same interactive feedback as types.

An example would look something like below:

```scheme
(define (factorial n)
  (if (< n 2) 1 (* n (- n 1))))

(with-examples (factorial)
  (check-equal? (factorial 0) (*))
  (check-equal? (factorial 1) (* 1))
  (check-equal? (factorial 4) (* 1 2 3 4)) ; fail
  )

```

Currently, what I'm doing is [creating a sub-module](https://github.com/philnguyen/examples/blob/main/examples/private/main.rkt#L23) using `module*`, then requiring the enclosing module at `for-syntax` time. But the enclosing module may not necessarily export the function in general (e.g. it may just be a helper). So what I'm doing is whenever the programmer writes `(with-examples (name) _ ...)`, I generate a throwaway alias `name*` and provide it to the sub-module instead, which it renames back to `name`.

What I don't like about this approach is that there will be no arrow in DrRacket if I place the cursor on `factorial` in the sub-module.

My question: Is there a better way to do this in Racket, to `provide` only specifically to a sub-module, and not necessarily everyone?

Thanks!!

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [August 24, 2025, 12:52pm UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/2 "2025-08-24T12:52:24Z")

</div>

The typical way for a submodule to require the "public interface" of its outer module would be something like `(module* name (submod "..") ___)`.

```scheme
#lang racket/base

(define public 42)
(define private 43)

(provide (all-from-out racket/base)
         public)

(module* m (submod "..")
  (println public)) ;works, but using `private` would be an error

```

Not only does this limit `m` to exports, it goes through any contracts that might be attached at the module boundary (sometimes you might care).

This approach avoids needing to make aliases. However it doesn't seem to help with the main thing you didn't like about your approach:

> [@pcn](#):
>
> What I don't like about this approach is that there will be no arrow in DrRacket if I place the cursor on `factorial` in the sub-module.

The arrows aren't better -- there's just an arrow from `public` to `(submod "..")`. ☹

---

<div class="post-metadata">

**Author:** ![pcn](https://avatars.discourse-cdn.com/v4/letter/p/65b543/32.png) [@pcn](https://racket.discourse.group/u/pcn)\
**Post date:** [August 24, 2025, 5:02pm UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/3 "2025-08-24T17:02:05Z")

</div>

I see thanks!! So even in the expanded code, the arrow points to the module. That's why in the macro one, there's no arrow pointing back to the original ☹

```scheme
#lang racket/base

(define public 42)
(define private 43)

(provide (all-from-out racket/base)
         (rename-out [private private*])
         public)

(module* m (submod "..")
  (require (rename-in (submod "..") [private* private]))
  (println private)
  (println public))

```

---

<div class="post-metadata">

**Author:** ![robby](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/robby/32/7_2.png) [@robby](https://racket.discourse.group/u/robby)\
**Post date:** [August 25, 2025, 11:52am UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/4 "2025-08-25T11:52:34Z")

</div>

One thing you might try is to generate binders and references that have the right syntax locations, but are in dead code. You could use the `factorial` that's written at the top of `with-examples` both in the enclosing module (as a reference) and in the newly created module (as a binder) to get at least some arrows. Check Syntax doesn't care if you use an identifier with the same source location in multiple different unrelated scopes. It does it's best with what it finds. 🙂

I tried to write an example to illustrate but ran into trouble with the submodule. Are you doing some kind of hygiene bending operations on the generated submodule?

---

<div class="post-metadata">

**Author:** ![pcn](https://avatars.discourse-cdn.com/v4/letter/p/65b543/32.png) [@pcn](https://racket.discourse.group/u/pcn)\
**Post date:** [August 26, 2025, 6:19am UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/5 "2025-08-26T06:19:00Z")

</div>

Thanks Robby!! So actually I get two arrows now pointing to both binding positions, which is reasonable. I don't know how it happened and what I did differently 😃

Unreasonable question: We don't need to do anything for a submodule defined by `module*` to access the enclosing module's definitions if it's in the same phase:

```scheme
#lang racket/base

(define x 42)

(module* test #f
  (println x))

```

Is it possible to have the submodule access the enclosing module during the submodule's `for-syntax` phase without explicitly providing/requiring anything?

---

<div class="post-metadata">

**Author:** ![robby](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/robby/32/7_2.png) [@robby](https://racket.discourse.group/u/robby)\
**Post date:** [August 26, 2025, 3:15pm UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/6 "2025-08-26T15:15:01Z")

</div>

Glad to hear that helped!

Can you share a smallish example that is missing an arrow and let me know what you'd like to see, just for concreteness sake?

---

<div class="post-metadata">

**Author:** ![pcn](https://avatars.discourse-cdn.com/v4/letter/p/65b543/32.png) [@pcn](https://racket.discourse.group/u/pcn)\
**Post date:** [August 27, 2025, 7:10am UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/7 "2025-08-27T07:10:03Z")

</div>

In this example:

```scheme
#lang racket/base

(require examples)
(define x 42)

(with-examples (x)
  (check-equal? x 42))

```

I already get the arrow from `x` pointing to the two bindings, which I think is the right thing.

The `with-examples` form is [expanding](https://github.com/philnguyen/examples/blob/main/examples/private/main.rkt#L14) to:

```scheme
(begin
  (provide (rename-out [x x*])) ; so `x` isn't exposed to public in general
  (module* anon #f
    (require (for-syntax racket/base
                         (rename-in (submod "..") [x* x])))
    (begin-for-syntax
      (check-equal? x 42))))

```

I think the reason I finally get 2 arrows now (one pointing to the original `x`) is because I'm declaring `#f` instead of `(submod "..")` like I used to do. So as far as arrow is concerned, I'm good now 😀

My possibly unreasonable question is, if it is possible to not have to explicitly provide/require private bindings from the enclosing module and have it available in the `for-syntax` phase of the submodule, something hypothetically like below 🙃?

```scheme
(module* anon (for-syntax #f) ; (not a thing)
  (begin-for-syntax
    (check-equal? x 42)))

```

---

<div class="post-metadata">

**Author:** ![pcn](https://avatars.discourse-cdn.com/v4/letter/p/65b543/32.png) [@pcn](https://racket.discourse.group/u/pcn)\
**Post date:** [August 27, 2025, 7:15am UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/8 "2025-08-27T07:15:05Z")

</div>

I probably should rename `with-examples` to `static-module+` or something to mirror `module+`. But a name starting with `with` naturally has the indentation I want 😁

---

<div class="post-metadata">

**Author:** ![robby](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/robby/32/7_2.png) [@robby](https://racket.discourse.group/u/robby)\
**Post date:** [August 27, 2025, 8:17pm UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/9 "2025-08-27T20:17:24Z")

</div>

Okay

> [@pcn](#):
>
> My possibly unreasonable question is, if it is possible to not have to explicitly provide/require private bindings from the enclosing module and have it available in the `for-syntax` phase of the submodule, something hypothetically like below 🙃?
> 
> ```scheme
> (module* anon (for-syntax #f) ; (not a thing)
> (begin-for-syntax
> (check-equal? x 42)))
> 
> ```

Oh! I thought you were asking for a change to check syntax that might make more arrows appear automatically without needing to make up binders and whatnot.

I don't know an answer to this one!

---

<div class="post-metadata">

**Author:** ![pcn](https://avatars.discourse-cdn.com/v4/letter/p/65b543/32.png) [@pcn](https://racket.discourse.group/u/pcn)\
**Post date:** [October 11, 2025, 9:27pm UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/10 "2025-10-11T21:27:29Z")

</div>

I'm revisiting this question, trying not to make users explicitly provide all the names to the sub-module, potentially giving up the arrows if that's infeasible.

The macro `with-examples` then would be used like this:

```scheme
#lang racket/base

(define n 42)

(with-examples
 (displayln n) ; prints 42 at compile time
 )

```

It would expand to something like this:

```scheme
#lang racket/base

(define n 42)

(module* all-defns #f
  (provide (all-from-out (submod "..")))
  (module* compile-time-exec #f
    (require (for-syntax racket/base
                         (submod "..")))
    (begin-for-syntax
      (displayln n))))

; Still printing 42 at compile time

```

But at the moment, I don't know where to get the context to assign to the `body ...` of the macro, so that I can both preserve the original source locations (for precise error reporting), and get the bindings from `(submod "..")`:

```scheme
(define-syntax-parser with-examples
  [(with-examples body ...)
   #:with racket/base (datum->syntax #'with-examples 'racket/base)
   #'(module* all-defns #f
       (provide (all-from-out (submod "..")))
       (module* compile-time-exec #f
         (require (for-syntax racket/base
                              (submod "..")))
         (begin-for-syntax
           body ... ; Won't see bindings from (submod "..")
           )))])

(with-examples
 (displayln n) ; ERROR: n undefined
 )

```

How can I get `body ...` to see the bindings from the `(submod ..)` in the generated `(module* compile-time-exec ...)`?

Thanks!!

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [October 11, 2025, 10:43pm UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/11 "2025-10-11T22:43:10Z")

</div>

> [@pcn](#):
>
> But at the moment, I don't know where to get the context to assign to the `body ...` of the macro, so that I can both preserve the original source locations (for precise error reporting), and get the bindings from `(submod "..")`:

The scope “on the parentheses” of the `(submod "..")` form is used for the imported bindings. This distinction is important so that the binding for `submod` still comes from the macro definition site, in case the usual binding isn't available at the use site.

Here's a worked-out example:

```scheme
#lang racket

(require syntax/parse/define)

(define-syntax-parser with-examples
  [(_ body ...)
   #:with racket/base (datum->syntax this-syntax #'racket/base)
   #:with submod.. (datum->syntax this-syntax (list #'submod #'".."))
   #'(module* all-defns #f
       (provide (all-from-out submod..))
       (module* compile-time-exec #f
         (require (for-syntax racket/base
                              submod..))
         (begin-for-syntax
           body ...)))])

(define n 42)

(with-examples
 (displayln n))

```

I also changed to use `this-syntax` instead of binding and using `#'with-examples`: that would allow some other macro that would expand to `with-examples` to work like the `(submod "..")` case.

> [@pcn](#):
>
> potentially giving up the arrows if that's infeasible

I'm not sure if there's a way to do this or not, and I've only skimmed the rest of this thread (so I'm likewise not getting into whether it should check `syntax-local-context` or `syntax-local-lift-module-end-declaration` or something to work multiple times).

But one thing to note is that `(require (submod ".."))` imports the identifiers exported by the parent module, potentially shadowing un-exported identifiers with the same names. The most common example is contracts:

```scheme
#lang racket
(define (buggy-generate-string)
  'not-a-string)
(provide (contract-out
          [buggy-generate-string
           (-> string?)]))
(module* implicit #f
  (provide implicit)
  (define (implicit)
    (buggy-generate-string)))
(module* explicit #f
  (require (submod ".."))
  (provide explicit)
  (define (explicit)
    (buggy-generate-string)))
(module* main racket
  (require (submod ".." implicit))
  (require (submod ".." explicit))
  `([implicit ,(implicit)]
    [explicit ,(with-handlers ([exn:fail? values])
                 (explicit))]))

```

---

<div class="post-metadata">

**Author:** ![pcn](https://avatars.discourse-cdn.com/v4/letter/p/65b543/32.png) [@pcn](https://racket.discourse.group/u/pcn)\
**Post date:** [October 12, 2025, 12:06am UTC](https://racket.discourse.group/t/providing-name-only-to-sub-module/3918/12 "2025-10-12T00:06:45Z")

</div>

Thank you so much!!
