Unexpected behaviour of quasiquote when binding unquote and unquote-splicing

#lang racket/base

(let ((unquote-splicing 4) (unquote add1))
   `(a b unquote ,(map unquote '(0 1 2 3)) ,(unquote unquote-splicing))) 

-->

(a b unquote ,(map . ,'(0 1 2 3)) ,,unquote-splicing)

but should it not produce:

(a b unquote (1 2 3 4) 5)

???

It seems that in parts of a datum in (quasiquote datum) at evaluation level
syntax quasiquote does not see the rebinding of unquote and unquote-splicing.

I do not have this problem in my own toy interpreters.

To explain what's going on, the reader shorthands `_ ,_ ,@_ are unhygienic in Racket. They stand for two-element lists with symbols at the beginning, (quasiquote _) (unquote _) (unquote-splicing _). They always mean whatever they would mean if you spelled them out.

This is a pretty weird situation, since (let ...) bindings don't interact with the behavior of most reader syntaxes, just `_ ,_ ,@_ #`_ #,_ #,@_. Rebinding unquote, as you've done, also effectively rebinds the meaning of ,_. If it helps any to tolerate this, consider that rebinding unquote also rebinds the meanings of |unquote|, un\quote, and #ci UnQuote, Of course, those are a little different from a practical standpoint since the symbols they represent are more apparent in their textual form.

If you'd like to use Racket with the hygienic behavior you want now, Alex Knauth has made the hygienic-quote-lang package for this situation. Just now I tried your example in #lang hygienic-quote racket, and it produced what you said it should.

3 Likes

To rocketnia

Thanks for the explanation.

Jos