tehkonst
tehkonst

Reputation: 195

Racket. Recognize special symbols in macro pattern

As an example the macro defines variables with symbols with the same name.

(define-syntax-rule (define-as-symbols args ...)
  (define-values (args ...) (apply values (quote (args ...)))))

(define-as-symbols A B C)
(println A) ; -> 'A
(println B) ; -> 'B
(println C) ; -> 'C

Can I change the macro so it works this way:

(define-as-symbols ignore / ignore / A B C)
(println A) ; -> 'A
(println B) ; -> 'B
(println C) ; -> 'C

It has to ignore the arguments before the last slash.

Upvotes: 2

Views: 68

Answers (1)

Shawn
Shawn

Reputation: 52354

You can do something like this to recursively eat up the ignore / bits, one pair at a time:

#lang racket/base

(define-syntax define-as-symbols
  (syntax-rules (/)
    ((_ ignore / rest ...) ; Has to come first to match
     (define-as-symbols rest ...))
    ((_ args ...)
     (define-values (args ...) (values 'args ...)))))

(define-as-symbols 0 / 1 / A B C)
(println A)

Or using the much more advanced syntax-parse macro system:

#lang racket/base

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

(define-syntax (define-as-symbols stx)
  (syntax-parse stx
    #:literals (/)
    [(_ (~seq ignore /) ... args:id ...+)
     (syntax/loc stx (define-values (args ...) (values 'args ...)))]))

(define-as-symbols #t / '() / A B C)
(println A)

This one has a bonus: Using a non-symbol in the args will raise a compile-time syntax error, as will having no symbols at all.

Upvotes: 3

Related Questions