~literal vs ~datum

70 views
Skip to first unread message

Jordan Johnson

unread,
Aug 1, 2017, 2:12:00 PM8/1/17
to Racket Users
Hi all,

Reading the documentation on ~datum in syntax/parse, I see:

The ~datum form is useful for recognizing identifiers symbolically, in contrast to the ~literal form, which recognizes them by binding.

That makes sense to me. But then I see:

> (syntax-parse (let ([define 'something-else]) #'(define x y))
    [((~datum define) var:id e:expr) 'yes]
    [_ 'no])
'yes
> (syntax-parse (let ([define 'something-else]) #'(define x y))
    [((~literal define) var:id e:expr) 'yes]
    [_ 'no])
'yes

I’m confused by this. It seems, based on the first sentence I quoted, that in the second example, in which the syntax being parsed has define bound to something other than the usual, the use of ~literal should make the first clause fail to match. And I’d have expected the examples to contrast ~datum and ~literal, rather than exhibit the same behavior.

Could someone please explain this to me?

Thanks,
Jordan

Jens Axel Søgaard

unread,
Aug 1, 2017, 2:34:36 PM8/1/17
to Jordan Johnson, Racket Users
The binding information is attached a syntax object during expansion.
In your example the #'(define x y) haven't gone through expansion,
so you do not get what your expected result.

However we can change your macro a little:


#lang racket
(require (for-syntax syntax/parse))

(define-syntax (is-define? stx)
  (syntax-parse stx
    [(_is-define? id)
     (syntax-parse #'id
       [(~literal define) #''yes]
       [_                 #''no])]))

(is-define? define)

(let ([define 42])
  (is-define? define))

This will result in

'yes
'no


/Jens Axel

Jordan Johnson

unread,
Aug 3, 2017, 1:53:34 AM8/3/17
to Racket Users
On Aug 1, 2017, at 11:34, Jens Axel Søgaard <jens...@soegaard.net> wrote:
The binding information is attached a syntax object during expansion.
In your example the #'(define x y) haven't gone through expansion,
so you do not get what your expected result.

However we can change your macro a little...

Ah, that clarifies everything. Thanks!

So, the example I quoted is actually from the docs on ~datum, and it seems pretty clear that it’s trying unsuccessfully to elicit different behaviors that show the difference between ~literal and ~datum. Based on the code you’ve provided, I think this would be a better illustration:

(define-syntax (is-define? stx)
  (syntax-parse stx
    [(_is-define? id)
     (syntax-parse #'id
       [(~literal define) #''yes]
       [(~datum   define) #''not-really]
       [_                 #''not-even-close])]))

(is-define? define)         ;; 'yes

(let ([define 42])
  (is-define? define))      ;; 'not-really

(is-define? something-else) ;; 'not-even-close

I’ve submitted that as a PR on the doc file linked above. I hope you don’t mind my using your example in that way. It was very helpful.

Regards,
Jordan

Shu-Hung You

unread,
Sep 11, 2017, 11:22:09 AM9/11/17
to Jordan Johnson, Racket Users
I think the case here is a little subtle. The syntax object #'(define
x y) has actually gone through expansion, but Racket's new expansion
model will prune this syntax object's local scopes [1]. One could use
#:local [2] in this case to see the difference:

> (syntax-parse (let ([define 'something-else]) (quote-syntax (define x y)))
[((~literal define) var:id e:expr) 'yes]
[_ 'no])
'yes

> (syntax-parse (let ([define 'something-else]) (quote-syntax (define x y) #:local))
[((~literal define) var:id e:expr) 'yes]
[_ 'no])
'no

The original doc predates the new expander and the result was probably
'no in the old expansion model.

Best,
Shu-Hung

1. http://www.cs.utah.edu/plt/scope-sets/general-macros.html#%28part._.Local_.Bindings_and_.Syntax_.Quoting%29

2. https://docs.racket-lang.org/reference/Syntax_Quoting__quote-syntax.html
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages