# Transparent Quotes

**URL:** <https://racket.discourse.group/t/transparent-quotes/4317>\
**Category:** Show & Tell\
**Created:** [July 13, 2026, 2:36pm UTC](https://racket.discourse.group/t/transparent-quotes/4317 "2026-07-13T14:36:00Z")\
**Posts on this page:** 1\
**Page:** 1

<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:** [July 13, 2026, 2:36pm UTC](https://racket.discourse.group/t/transparent-quotes/4317/1 "2026-07-13T14:36:00Z")

</div>

Hi, Racket Discourse.

This is something I've looked at before, in reference to @notjack's [`name` and `name-string`](https://github.com/jackfirth/rebellion/blob/master/private/static-name.rkt) under the private modules for [Rebellion](https://docs.racket-lang.org/rebellion/index.html).

I thought about it again today while using `C#`'s `nameof` keyword and decided I'd try to figure it out in Racket because I bounced off the idea the last time around.

The part that was befuddling to me, was how to track the identifier as a literal (which I now say with the benefit of hindsight), given that we want to `quote` it, and that generally cuts it off from the rest of the context.

We can do that using the [`syntax-parse-state-cons!`](https://docs.racket-lang.org/syntax/state.html#%28def._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse-state-cons%21%29%29) procedure, which allows one to manually update the state of `syntax-parse`. This affords finer-grained control over the info attached to certain syntax.

It so turns out, after reading `static-name.rkt` more carefully--and trying to run the bits in isolation--that the consequential snippet was `(syntax-parse-state-cons! 'literals id)`. To wit, from the docs:

> In addition, [syntax-parse](https://docs.racket-lang.org/syntax/Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29) automatically adds identifiers that match literals (from [~literal](https://docs.racket-lang.org/syntax/stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._~7eliteral%29%29) patterns and literals declared with #:literals, but not from [~datum](https://docs.racket-lang.org/syntax/stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._~7edatum%29%29) or #:datum-literals) under the key 'literals.

Anyways, the resulting code is nice and simple:

```scheme
#lang racket/base

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

(define-syntax-parse-rule (quote/literal id)
  #:do [(syntax-parse-state-cons! 'literals #'id)]
  (quote id))

(define-syntax-parse-rule (symbolof id:id)
  #:fail-unless (identifier-binding #'id)
  "expected a bound identifier"
  (quote/literal id))

(define-syntax-parse-rule (stringof id:id)
  #:fail-unless (identifier-binding #'id)
  "expected a bound identifier"
  (symbol->immutable-string (quote/literal id)))

(define (foo arg) (stringof foo))
(define bar 4)

(foo 'ignored)
(symbolof bar)
(stringof bar)

```

```scheme
"foo"
'bar
"bar"
>

```

 ![image](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/3/31319431556d4a63146f8a32ae8551ca80ca0c59.png)

I am ambivalent about the names, specifically, but at least they do what they say on the tin.

Mooiloop.
