# Question About Macro Bindings

**URL:** <https://racket.discourse.group/t/question-about-macro-bindings/2033>\
**Category:** Questions & Answers\
**Tags:** question, macro, binding\
**Created:** [June 21, 2023, 2:22pm UTC](https://racket.discourse.group/t/question-about-macro-bindings/2033 "2023-06-21T14:22:29Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![jschappel](https://avatars.discourse-cdn.com/v4/letter/j/bbce88/32.png) [@jschappel](https://racket.discourse.group/u/jschappel)\
**Post date:** [June 21, 2023, 2:22pm UTC](https://racket.discourse.group/t/question-about-macro-bindings/2033/1 "2023-06-21T14:22:29Z")

</div>

Hello 👋! I am tying to write 2 simple macros where one renames a identifier by appending $ to the beginning and end. The other returns the newly created identifiers in a list.

```scheme
#lang racket
(require
 (for-syntax syntax/parse
             racket/syntax
             syntax/stx))
(provide def id-list)

(define-syntax (def stx)
  (syntax-parse stx
    [(_ id:id val:expr)
     #:with new-id (format-id #'id "$~a$" #'id)
     #`(define new-id val)]))

(define-syntax (id-list stx)
  (syntax-parse stx
    [(_ ids:id ...)
     #:with (new-ids ...) (stx-map (lambda (i) (format-id #`i "$~a$" i)) #`(ids ...))
     #`(list new-ids ...)]))

(def x 10)
(def y 20)
(id-list x y)

```

This works as expected when I call the macro from within the module that it was created, however when I try the run the code from another module or submodule I get an unbound identifier error. I have a feeling this has to do with [binding and phase levels](https://docs.racket-lang.org/reference/syntax-model.html#%28tech._binding%29), but after reading the docs I am still confused. Any help is appreciated.

-Josh

Example:

```scheme
(module+ test
  (def x 10)
  (def y 20)

  (id-list x y))

; $x$: unbound identifier
; in: $x$
; context...:
; #(1376184 macro) #(1376187 local) #(1376188 intdef) [common scopes]
; other binding...:
; #($x$ #<module-path-index=(submod 'test[2358842] test)> 0)
; #(1376160 module) [common scopes]
; common scopes...:
; #(1375539 module) #(1375546 module test) #(1376167 module test)

```

---

<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:** [June 21, 2023, 3:00pm UTC](https://racket.discourse.group/t/question-about-macro-bindings/2033/2 "2023-06-21T15:00:22Z")

</div>

In your `id-list` macro, you have:

`#`i`

in the call of `format-id`. You probably meant to write just `i`.

In `def`, you need to put `#'` in front of `id` because `id` is a syntax pattern. But in `id-list`, `i` is just a regular variable, so you should not put `#'` in front of it.

---

<div class="post-metadata">

**Author:** ![jschappel](https://avatars.discourse-cdn.com/v4/letter/j/bbce88/32.png) [@jschappel](https://racket.discourse.group/u/jschappel)\
**Post date:** [June 21, 2023, 3:08pm UTC](https://racket.discourse.group/t/question-about-macro-bindings/2033/4 "2023-06-21T15:08:13Z")

</div>

Thank you for the explanation!

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [June 21, 2023, 3:09pm UTC](https://racket.discourse.group/t/question-about-macro-bindings/2033/5 "2023-06-21T15:09:37Z")

</div>

Try something like this:

```scheme
#lang racket
(provide def id-list)

(require (for-syntax syntax/parse racket/syntax syntax/stx))

(begin-for-syntax
  (define common-ctx #'common-context-for-def-and-id-list))

(define-syntax (def stx)
  (syntax-parse stx
    [(_ id:id val:expr)
     #:with new-id (syntax-local-introduce (format-id common-ctx "$~a$" #'id))
     #'(define new-id val)]))

(define-syntax (id-list stx)
  (syntax-parse stx
    [(_ ids:id ...)
     #:with (new-ids ...) (stx-map (λ (i) (format-id common-ctx "$~a$" i))
                                   #'(ids ...))
     #'(list new-ids ...)]))

;(def x 10) (def y 20) (id-list x y)

(module+ test
  (def x 10)
  (def y 20)

  (id-list x y))

```

The idea here is to make the common scope for identifiers in `def` and `id-list` explicit.

> Roughly, every binding form and macro expansion creates a scope, and each fragment of syntax acquires a set of scopes that determines binding of identifiers within the fragment. In a language without macros, each scope set is identifiable by a single innermost scope. In a language with macros, identifiers acquire scope sets that overlap in more general ways.

When the identifier in `id-list` is "recreated" the part of the scope from the macro expansion of `def` is missing. The snippet above uses `syntax-local-introduce` to fix that.

---

<div class="post-metadata">

**Author:** ![jschappel](https://avatars.discourse-cdn.com/v4/letter/j/bbce88/32.png) [@jschappel](https://racket.discourse.group/u/jschappel)\
**Post date:** [June 21, 2023, 3:19pm UTC](https://racket.discourse.group/t/question-about-macro-bindings/2033/6 "2023-06-21T15:19:59Z")

</div>

It seems like @sorawee's replay was able to fix the issue. Is there a added benefit to creating a common scope for identifiers as your suggesting?

Also would you mind elaborating (or pointing me to some racket docs) that discuss the below in more detail?

> identifiers acquire scope sets that overlap in more general ways.

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [June 21, 2023, 3:45pm UTC](https://racket.discourse.group/t/question-about-macro-bindings/2033/7 "2023-06-21T15:45:51Z")

</div>

> [@jschappel](#):
>
> It seems like @sorawee's replay was able to fix the issue. Is there a added benefit to creating a common scope for identifiers as your suggesting?

Nothing more that making the connection between the two macros explicit.

> [@jschappel](#):
>
> Also would you mind elaborating (or pointing me to some racket docs) that discuss the below in more detail?
> 
> > identifiers acquire scope sets that overlap in more general ways.

I can recommend:

[![](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/d/d78f207e84e1e0891682a664882ed8fa468fa84b.jpeg "(fifth RacketCon): Matthew Flatt — Bindings as Sets of Scopes") ](https://www.youtube.com/watch?v=ABWLveMNdzg)

---

<div class="post-metadata">

**Author:** ![jschappel](https://avatars.discourse-cdn.com/v4/letter/j/bbce88/32.png) [@jschappel](https://racket.discourse.group/u/jschappel)\
**Post date:** [June 21, 2023, 3:50pm UTC](https://racket.discourse.group/t/question-about-macro-bindings/2033/8 "2023-06-21T15:50:06Z")

</div>

Awesome! I will take a look at it. Thanks for all your help!
