Sam
Sam

Reputation: 796

Use a syntax list as formal parameters to a function

This is the scenario: Given a pattern of the form [sym ...] (e.g. [a b] and [a b c d]) I want to generate (using macros) functions that concatenate the symbols in the pattern, but also supply them as arguments. For example, [a b] transforms to something of the form

(define (ab a b) 
  body)

In this post someone helps me generate the name of the function via a syntax class called signal-list. In the following code I can match the signals pattern variable with a pattern of the form (sig ...), and I can then use it to generate the desired function definition.

(define-syntax (define-something stx)
  (syntax-parse stx
    [(_ (signals:signal-list body ...))
     (syntax-parse #'signals
       [(sig ...)
        #'(define (signals.concatenated-ids sig ...)
               body ...)])]))

An example that matches this macro:

(define-something
  ([a b] 'body))

which expands to (define (ab a b) 'body)

But how do macros work if I want to generate multiple function definitions? For example:

(define-something
  ([a b] 'body)
  ([c d e] 'body))
=>
(begin (define (ab a b) 'body)
       (define (cde c d e) 'body))

I can add an ellipsis in the pattern of the first syntax-parse:

(_ (signals:signal-list body ...) ...)

But then I cannot use the second syntax-parse to match against signals because it needs an ellipsis. Is there a different way to 'de-construct' signals so that I can use its contents as formal parameters to a function, which is compatible with using ellipses?

Upvotes: 2

Views: 68

Answers (1)

C. K. Young
C. K. Young

Reputation: 222973

To directly answer your question, you can pass #'(signals ...) (in place of your existing #'signals) to the inner syntax-parse invocation.


As a proof of concept, I wrote a syntax-case version of your macro (since I don't know syntax-parse yet). You should be able to adapt the same technique to syntax-parse easily:

(define-syntax (define-something outerstx)
  (define (make-name paramstx)
    (datum->syntax outerstx
                   (string->symbol
                    (apply string-append
                           (map symbol->string (syntax->datum paramstx))))))

  (define (make-names innerstx)
    (syntax-case innerstx ()
      (()
       #'())
      (((param ...) rest ...)
       (with-syntax ((name (make-name #'(param ...)))
                     ((next ...) (make-names #'(rest ...))))
         #'(name next ...)))))

  (syntax-case outerstx ()
    ((_ ((param ...) body ...)
        ...)
     (with-syntax (((name ...) (make-names #'((param ...) ...))))
       #'(define-values (name ...)
           (values (lambda (param ...)
                     body ...)
                   ...))))))

Upvotes: 2

Related Questions