Why would `second` being unbound identifier inside `syntax->datum`?

In this program, ok and ok2 only differs at cadr & second

#lang racket
(second '(1 2 3))

(define-syntax (ok stx)
  (datum->syntax stx (let ([s (syntax->datum stx)])
    (cadr s))))

(ok 1 2 3)

(define-syntax (ok2 stx)
  (datum->syntax stx (let ([s (syntax->datum stx)])
   (second s))))

(ok2 1 2 3)

Run it will yield an error that second is unbound when defining of ok2

Why would it unbound?

It is clearly included with #lang racket.

second: reference to an unbound identifier
  at phase: 1; the transformer environment
  context...:
  matching binding...:
  common scopes...: in: second

Is this a bug? I am am using 8.10 [cs].

1 Like

You need to add a (require (for-syntax racket/list)) to get the definition of second at macro expansion time. See Compile and Run-Time Phases in the Racket Guide for details.

2 Likes

The #lang racket languages does include racket/list but only at runtime (phase 0).
At compile time (phase 1) the imports are from #lang racket/base which doesn't
include racket/list.

The cure as @shawnw mentions is to import racket/list for compile time using
(require (for-syntax racket/list)).

Note that second checks that the input is a list and cadr doesn't.
Therefore it might be better to use cadr depending on context.

Bonus tip: If you require syntax/stx for compile time, you can use stx-car and stx-cdr which work on both lists and syntax objects representing lists.

2 Likes

Thanks very for the explanations!

I didn't realize "compile and run-time differences" has this implication before.