# Using syntax/loc with ellipsis

**URL:** <https://racket.discourse.group/t/using-syntax-loc-with-ellipsis/3935>\
**Category:** Questions & Answers\
**Created:** [September 7, 2025, 4:19am UTC](https://racket.discourse.group/t/using-syntax-loc-with-ellipsis/3935 "2025-09-07T04:19:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![sora22](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/sora22/32/2622_2.png) [@sora22](https://racket.discourse.group/u/sora22)\
**Post date:** [September 7, 2025, 4:19am UTC](https://racket.discourse.group/t/using-syntax-loc-with-ellipsis/3935/1 "2025-09-07T04:19:49Z")

</div>

I'm currently writing a macro where I need to use syntax/loc in combination with an ellipsis, the following code is akin to the problem I'm having:

```scheme
#lang racket/base
(require (for-syntax racket/base
                     syntax/parse))

(define-syntax (example stx)
  (syntax-parse stx
    [(_ vals ...)
     #`(begin
         #,(syntax/loc stx #'vals)
         ...)]))

```

This causes an error with the pattern variable not catching that I am using an ellipsis. I've tried using with-syntax and template-metafunctions to no avail, does anyone know of a specific way in which I could use syntax/loc with the ellipsis?

---

<div class="post-metadata">

**Author:** ![bakgatviooldoos](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/bakgatviooldoos/32/1381_2.png) [@bakgatviooldoos](https://racket.discourse.group/u/bakgatviooldoos)\
**Post date:** [September 7, 2025, 10:07am UTC](https://racket.discourse.group/t/using-syntax-loc-with-ellipsis/3935/2 "2025-09-07T10:07:31Z")

</div>

Hi, @sora22.

It can be tricky to know "the shape" of these kinds of forms, but it is helpful to remember that `syntax/loc` is like `syntax`, i.e. `#'`, but with the source-location data from the `stx` in the first argument.

So, for example, this works:

```scheme
#lang racket/base

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

(define-syntax (example stx)
  (syntax-parse stx
    [(_ vals ...)
     #:attr val* (syntax/loc stx (vals ...))
     #'(begin . val*)]))

(example 14)
;=> 14

```

But that doesn't really answer your question.

I think technically what you want to do, is related to `quasisyntax/loc`, which is again, like ~~`quasisyntax`, i.e. `#,` but with source-location information from the relevant syntax.~~

Ag, and then I go and talk nonsense. `quasisyntax` is supposed to be related to "#`". The idea is there, I apologize for being a moron.

So, this also works:

```scheme
(define-syntax (example₂ stx)
  (syntax-parse stx
    [(_ vals ...)
     #`(begin #,@(quasisyntax/loc stx (vals ...)))]))

```

Other more experienced Racketeers will be able to give a more definitive answer, because I can only see the "shape" mismatch, but not necessarily the clear rationale for how this _should_ be done.

---

<div class="post-metadata">

**Author:** ![sora22](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/sora22/32/2622_2.png) [@sora22](https://racket.discourse.group/u/sora22)\
**Post date:** [September 7, 2025, 6:15pm UTC](https://racket.discourse.group/t/using-syntax-loc-with-ellipsis/3935/3 "2025-09-07T18:15:58Z")

</div>

I will try this approach out when I get back to my desktop, but unfortunately I suspect it probably wouldn't work for what I'm attempting to do. I think I may have oversimplified in attempt to get a minimal breaking example, my bad.

I'm trying to highlight specific values in the ellipsis because I'm using code to manipulate the values in the ellipsis that could cause an error if the macro is used incorrectly. Here is I think a closer albeit more abstract idea of what the problem I'm trying to solve is:

```scheme
#lang racket/base
(require (for-syntax racket/base
                     syntax/parse))

(define-syntax (example stx)
  (syntax-parse stx
    [(_ (ids vals) ...)
     #`(let
           ([ids #,(syntax/loc #'vals #'*Some code manipulating the value*)]
           ...)
         body)]))

```

I think I am not oversimplifying it this time (I hope), but it _seems_ to me I actually need the syntax/loc to be repeated by the ellipsis. I would be very happy to be wrong though, because I imagine it would make implementing proper syntax highlighting for my macro much easier

---

<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:** [September 7, 2025, 6:28pm UTC](https://racket.discourse.group/t/using-syntax-loc-with-ellipsis/3935/4 "2025-09-07T18:28:29Z")

</div>

You need to use `with-syntax` instead of using `unsyntax`.

```scheme
#lang racket/base
(require (for-syntax racket/base
                     racket/syntax
                     syntax/stx
                     syntax/parse))

(define-syntax (define-constants stx)
  (syntax-parse stx
    [(_define-constants (name ...) (expr ...))
     (define (prepend-$ x) (format-id x "$~a" x))     
     (with-syntax ([($name ...) (stx-map prepend-$ #'(name ...))])
       #'(begin
           (define $name expr)
           ...))]))

(define-constants (foo bar) (11 22))

(list $foo $bar)

```

This result is `'(11 22)`.

---

<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:** [September 7, 2025, 6:57pm UTC](https://racket.discourse.group/t/using-syntax-loc-with-ellipsis/3935/5 "2025-09-07T18:57:01Z")

</div>

As @soegaard's answer shows, the problem isn't specific to `syntax/loc`: the fundamental issue is that `...` can't handle _any_ template term that uses `unsyntax` (a.k.a. `#,`), because `...` doesn't know how to map the expression over (potentially nested) lists of pattern variables.

FWIW, if you are using `syntax-parse`, I would use `#:with` instead of `with-syntax`.

```scheme
#lang racket/base
(require (for-syntax racket/base
                     syntax/parse))

(define-syntax (example stx)
  (syntax-parse stx
    [(_ (id val) ...)
    #:with (rhs ...) (for/list ([val-expr (syntax->list #'(val ...))])
                       ;; do work here ...
                       (quasisyntax/loc val-expr #,val-expr))
     #`(let ([id rhs] ...)
         (list id ...))]))

(example [a 1] [b 2]) ; -> '(1 2)

```

> [@sora22](#):
>
> I'm using code to manipulate the values in the ellipsis that could cause an error if the macro is used incorrectly

Just to check, are you manipulating the “values” at compile time or at run time?

At compile time, you only have the syntax of the sub-expression (or, more generally, the sub-form): it isn't evaluated until runtime. So you might have `#'(+ 1 2)` instead of `#'3`. The best way to detect and report compile-time errors in macro subterms is to use `syntax/parse`'s syntax classes.

If, instead, you are manipulating the actual values at runtime, you should take a look at [1.2.6&nbsp;Contracts on Macro Sub-expressions](https://docs.racket-lang.org/syntax/exprc.html).

---

<div class="post-metadata">

**Author:** ![ryanc](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/ryanc/32/71_2.png) [@ryanc](https://racket.discourse.group/u/ryanc)\
**Post date:** [September 7, 2025, 9:19pm UTC](https://racket.discourse.group/t/using-syntax-loc-with-ellipsis/3935/6 "2025-09-07T21:19:54Z")

</div>

You cannot use `syntax/loc` like that, since you need `unsyntax` (`#,`) to use `syntax/loc`, and `unsyntax` does not cooperate with ellipses.

One important note about `syntax/loc`: it only places the location on the outermost syntactic structure (pair, usually), and _only if that structure originated from the syntax template_. If the syntax template is just a pattern variable, then `syntax/loc` does not change the location of the syntax that the variable refers to.

One solution is to use a helper macro that takes the original syntax as an argument:

```
(define-syntax (example stx)
  (syntax-parse stx
    [(_ val:expr ...)
     #`(begin
         (process/loc val #,stx)
         ...)]))

(define-syntax (process/loc stx)
  (syntax-parse stx
    [(_ val:expr orig-stx)
     (syntax/loc #'orig-stx
       (process val))]))

```

A similar solution is to use a template metafunction, but keep in mind that the metafunction is only useful for applying `syntax/loc` if it is responsible for creating the syntactic structure that gets the location. For example:

```
(define-syntax (example stx)
  (define-template-metafunction (~process/loc mstx)
    (syntax-parse mstx
      [(_ arg:expr)
       (syntax/loc stx ;; not mstx
         (process arg))]))
  (syntax-parse stx
    [(_ val:expr ...)
     #`(begin (~process/loc val) ...)]))

```

The following variant would _not_ set the source location as you want it:

```
(define-syntax (example stx)
  (define-template-metafunction (~loc mstx)
    (syntax-parse mstx
      [(_ arg:expr)
       (syntax/loc stx ;; NO EFFECT!
         arg)]))
  (syntax-parse stx
    [(_ val:expr ...)
     #`(begin (~loc (process val)) ...)]))

```

---

<div class="post-metadata">

**Author:** ![sora22](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/sora22/32/2622_2.png) [@sora22](https://racket.discourse.group/u/sora22)\
**Post date:** [September 11, 2025, 7:40am UTC](https://racket.discourse.group/t/using-syntax-loc-with-ellipsis/3935/7 "2025-09-11T07:40:08Z")

</div>

> [@LiberalArtist](#):
>
> If, instead, you are manipulating the actual values at runtime, you should take a look at [1.2.6 Contracts on Macro Sub-expressions](https://docs.racket-lang.org/syntax/exprc.html).

I am, however I am working with a colleague who has already created contracts which I would have to essentially decompose and reapply to the various arguments (its easier to just redirect the syntax highlighting in this particular case). I tried this since it seems to be one proper way to achieve the granular highlighting I'm looking for, but I appear to still be running into similar issues [I've had previously in regard to syntax highlighting](https://racket.discourse.group/t/expr-c-and-wrap-expr-c-not-error-highlighting-what-contract-states-it-is-blaming/3369).

> [@ryanc](#):
>
> One solution is to use a helper macro that takes the original syntax as an argument:
> 
> ```scheme
> (define-syntax (example stx)
> (syntax-parse stx
> [(_ val:expr ...)
> #`(begin
> (process/loc val #,stx)
> ...)]))
> 
> (define-syntax (process/loc stx)
> (syntax-parse stx
> [(_ val:expr orig-stx)
> (syntax/loc #'orig-stx
> (process val))]))
> 
> ```

I did get this to work when using "stx" as the location expression, but as expected it highlights the entire expression rather than the specific subexpression. I was hopeful that using the values of the ellipsis as the location expression would work, however when using them as the location expression I seemed to be causing some inordinate amount of work somewhere (I've never waited longer than 30 seconds to a minute before killing the program, so maybe it will terminate but it's still excessive).

The final thing I've tried since is using with-handlers to re-raise the exception with a srcloc. This appears like it would work if I could differentiate which contract raised the exception with the predicate. I haven't looked too deeply into this yet, so maybe I'm just not aware of how to differentiate them.

For the time being I think I'll use the helper macro suggested by @ryanc but I am still looking for a way to highlight specific expressions. If I can't figure out a way to differentiate which contract raised the exception I'll probably attempt to combine expr/c with with-handlers next? Not the most elegant solutions unfortunately...

By the way, thank you all for your help in trying to figure this out, its very appreciated

---

<div class="post-metadata">

**Author:** ![sora22](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/sora22/32/2622_2.png) [@sora22](https://racket.discourse.group/u/sora22)\
**Post date:** [October 28, 2025, 6:56pm UTC](https://racket.discourse.group/t/using-syntax-loc-with-ellipsis/3935/8 "2025-10-28T18:56:53Z")

</div>

I think I ended up finding my solution in syntax splicing. I certainly have much more to learn with in regards to syntax splicing, but the following code _seems_ to have achieved what I was looking to do:

```scheme
(define-syntax (example stx)
  (syntax-parse stx
    [(_ val:expr ...)
     #`(begin
         ;; Some code ...
         #,@(for/list ([a-stx (in-list (syntax-e #'(val ...)))])
              (quasisyntax/loc a-stx
                ***some syntax*** )))]))

```

Again, no idea if this is a good idea/if this is how syntax splicing was meant to be used, still trying to figure that out myself. But if anyone else is looking for a potential solution, it achieves what I originally set out to do
