# Cannot (require ...) in module inside macro

**URL:** https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241
**Category:** Questions & Answers
**Created:** [August 24, 2023, 2:47am UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241 "2023-08-24T02:47:28Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![axmx](https://avatars.discourse-cdn.com/v4/letter/a/2bfe46/32.png) [@axmx](https://racket.discourse.group/u/axmx)
#### Post date: [August 24, 2023, 2:47am UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/1 "2023-08-24T02:47:28Z")

</div>

When using (require rackunit) in a macro, the identifiers are not properly imported, and I get this error:

```scheme
test2.rkt:11:1: check-equal: unbound identifier
  in: check-equal
  #(169 11)

```

Minimal example:

```scheme
#lang racket

(require (for-syntax syntax/parse))

(define-syntax (require-rackunit stx)
  (syntax-parse stx
    ((_)
     #'(require rackunit))))

(require-rackunit)
(check-equal 1 1)

```

The macro stepper confirms it was expanded correctly:

```scheme
(module test2 racket (#%module-begin (require (for-syntax syntax/parse)) (define-syntax (require-rackunit stx) (syntax-parse stx ((_) #'(require rackunit)))) (require-rackunit) (check-equal 1 1)))

→ [Macro transformation]

(module test2 racket (#%module-begin (require (for-syntax syntax/parse)) (define-syntax (require-rackunit stx) (syntax-parse stx ((_) #'(require rackunit)))) (require rackunit) (check-equal 1 1)))

```

This is not limited to rackunit, it seems like racket cannot (require ...) anything inside a macro.

---

<div class="post-metadata">

### Author: ![sorawee](https://avatars.discourse-cdn.com/v4/letter/s/ea5d25/32.png) [@sorawee](https://racket.discourse.group/u/sorawee)
#### Post date: [August 24, 2023, 3:57am UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/2 "2023-08-24T03:57:23Z")

</div>

Two problems. The first one is that it should be `check-equal?`, not `check-equal`.

But fixing that will still result in the unbound id error. The [documentation](https://docs.racket-lang.org/reference/require.html) of `require` states:

> The lexical context of the module-path form determines the context of the introduced identifiers

The issue in your code is that inside a macro (e.g. `require-rackunit`), the lexical context is that of the macro, which is not the right lexical context to be used.

One possible fix is:

```scheme
(define-syntax (require-rackunit stx)
  (syntax-parse stx
    ((_)
     #:with RACKUNIT (datum->syntax stx 'rackunit)
     #'(require RACKUNIT))))

```

This changes the lexical context of `rackunit` to the macro caller (`stx`), so your code will now work.

The code will fail again if you have another macro that calls `require-rackunit`, since the lexical context will be that of the outer macro. Arguably, that is the desirable result. But if you want that to work too, you need to keep threading the lexical context down, similar to what we are doing here.

---

<div class="post-metadata">

### Author: ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)
#### Post date: [August 24, 2023, 1:08pm UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/3 "2023-08-24T13:08:53Z")

</div>

Another alternative is to call `syntax-local-introduce` on the syntax object containing the require. (Not sure if that’s considered « good form ».)

---

<div class="post-metadata">

### Author: ![sorawee](https://avatars.discourse-cdn.com/v4/letter/s/ea5d25/32.png) [@sorawee](https://racket.discourse.group/u/sorawee)
#### Post date: [August 24, 2023, 1:35pm UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/4 "2023-08-24T13:35:56Z")

</div>

One downside of `syntax-local-introduce` is that if `require-rackunit` is exported from a module, and then imported to be used in another module, it won’t work properly.

It’s unfortunate that the example of `syntax-local-introduce` in the documentation kinda implies that this exact problem can be solved by using `syntax-local-introduce`, while there’s a caveat like this.

---

<div class="post-metadata">

### Author: ![axmx](https://avatars.discourse-cdn.com/v4/letter/a/2bfe46/32.png) [@axmx](https://racket.discourse.group/u/axmx)
#### Post date: [August 24, 2023, 1:36pm UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/5 "2023-08-24T13:36:37Z")

</div>

Thanks @sorawee and @benknoble.

I'm trying to attach unit tests to a function definition, similar to the "where" keyword in the pyret language. This is where I'm at right now:

```scheme
#!racket/base

(require (for-syntax syntax/parse racket/syntax racket/base))
(provide with-checks)

(define-syntax (with-checks stx)
  (syntax-parse stx
    ((_ def:expr checks:expr ...)
     (syntax-local-introduce #'(begin def
                                      (module+ test
                                        (require rackunit)
                                        checks ...))))))
   
(with-checks
  (define (f x) (+ x 1))
  (check-equal? (f 1) 2)
  (check-equal? (f 4) 6))

```

This works when I use with-checks in the same module, but not when I import with-checks in another module. I'm trying to convert it to use datum-\>syntax, and I understand that I need to bind the lexical scope of the "test" module to the "(require rackunit)", but not sure how to do it.

---

<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, 2023, 1:50pm UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/6 "2023-08-24T13:50:25Z")

</div>

[**EDIT** : Indeed this is N/A; more posts arrived while I was writing it and hit send. I guess I'll keep it, on the tiny chance it's useful to someone else someday.]

@sorawee gave a great answer to your specific question, @axmx, about your minimal example, where you define a macro to do a `require` at each site where the macro is used.

But I've rarely seen that done. If you're sure that's what want to do, and you're already familiar with Racket -- great; ignore the rest of this. 😄

More typically, you'd define some module, which `provide`s your own definitions and/or `require`s and re-`provide`s definitions from other modules.

Let's say `my-test-utils.rkt`:

```scheme
#lang racket/base
(require rackunit)
(provide (all-from-out rackunit)
         my-extra-test-stuff)
(define (my-extra-test-stuff) _TBD_)

```

Now any other module can `(require "my-test-utils.rkt")` to get your mix of standard `rackunit` stuff plus your extra stuff.

You could even package this up as a lang or meta-lang, as described in ["Languages as Dotfiles"](https://blog.racket-lang.org/2017/03/languages-as-dotfiles.html).

(Again apologies if you already know all this and want to do something else instead.)

---

<div class="post-metadata">

### Author: ![sorawee](https://avatars.discourse-cdn.com/v4/letter/s/ea5d25/32.png) [@sorawee](https://racket.discourse.group/u/sorawee)
#### Post date: [August 24, 2023, 2:04pm UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/7 "2023-08-24T14:04:25Z")

</div>

Well, this works for me.

```scheme
#lang racket

(module server racket
  (require (for-syntax syntax/parse racket/syntax racket/base))
  (provide with-checks)

  (define-syntax (with-checks stx)
    (syntax-parse stx
      ((_ def:expr checks:expr ...)
       #:with RACKUNIT (datum->syntax stx 'rackunit)
       #'(begin def
                (module+ test
                  (require RACKUNIT)
                  checks ...))))))

(require 'server)

(with-checks
    (define (f x) (+ x 1))
  (check-equal? (f 1) 2)
  (check-equal? (f 4) 6))

```

Keep in mind that Pyret’s function definition with a where clause does not faithfully translate into the test submodule. For one, a function definition with a where clause can appear at non-module context (e.g., nested within another function definition). But the expansion to the test submodule mandates that you must be at the module context. (You can probably use something like `syntax-local-lift-module` to workaround that though.)

---

<div class="post-metadata">

### Author: ![axmx](https://avatars.discourse-cdn.com/v4/letter/a/2bfe46/32.png) [@axmx](https://racket.discourse.group/u/axmx)
#### Post date: [August 24, 2023, 3:00pm UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/8 "2023-08-24T15:00:00Z")

</div>

Yes that works, once I remembered to correct the `check-equal/check-equal?` thing. 🤦‍♂️

I only want to test top-level function definitions, so it's fine that the macro doesn't exactly match pyret `where` behavior.

Thanks all!

---

<div class="post-metadata">

### Author: ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)
#### Post date: [August 24, 2023, 3:52pm UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/9 "2023-08-24T15:52:12Z")

</div>

Wait, really? I wasn’t aware of that drawback. Does the datum-\>syntax manipulation not have it? I suppose not, since you manipulate the contexts explicitly…

---

<div class="post-metadata">

### Author: ![EmEf](https://avatars.discourse-cdn.com/v4/letter/e/53a042/32.png) [@EmEf](https://racket.discourse.group/u/EmEf)
#### Post date: [August 24, 2023, 9:40pm UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/10 "2023-08-24T21:40:29Z")

</div>

Consider `local-require` to get closer to Pyret.

---

<div class="post-metadata">

### Author: ![shhyou](https://avatars.discourse-cdn.com/v4/letter/s/ccd318/32.png) [@shhyou](https://racket.discourse.group/u/shhyou)
#### Post date: [August 25, 2023, 1:05am UTC](https://racket.discourse.group/t/cannot-require-in-module-inside-macro/2241/11 "2023-08-25T01:05:02Z")

</div>

My understanding is that `datum->syntax`-ish or other related operations is the way to go precisely because of the issue with modules. `syntax-local-introduce` flips the fresh macro scope and the use-site scope but doesn't take care of module scopes.
