4
votes

Given:

(define-syntax (test stx)
  (syntax-case stx ()
    [(_ body ...)
     (with-syntax ([body0 (process-body #'(body ...))])
       #'body0)]))

How should I receive the pattern and the ellipses in the helper? I'm not even sure if wrapping the body ... inside () is correct, but I've seen it around and it's the only thing that doesn't crash.

The process-body procedure ends up with syntax that has extra () wrapping it. I can try and break this apart, but I'm just wondering what the correct way to do this is.

process-body wraps the body pattern with some code before AND after. And, similar to define, I want to be able to provide the macro with multiple forms rather than all forms in one list. So, if given (form1) (form2), where form2 is the ellipses, process-body should (do-something) (form1) (form2) (do-something-else).

ie,

(define-for-syntax (process-body body-syntax)
  (with-syntax ([stx body-syntax])
    (syntax/loc body-syntax
      (λ (request)
         stx))))

Of course I have this working when I define the template in-line, and I suppose I could do that here, but sometimes the template becomes unwieldy and it's nice to call a helper.

Thanks a lot.

As an edit to try dyoo's first example, I'm providing the following:

#lang racket

(define-syntax (test2 stx)
  (syntax-case stx ()
    [(_ body ...)
     (with-syntax ([(body0 ...) (process-body2 #'(body ...))])
       #'(begin body0 ...))]))

(define-for-syntax (process-body2 bodies)
  (with-syntax ([(body ...) bodies])
    (syntax/loc bodies
      (λ (request)
         body ...))))

(test2 (print "hi"))

λ: bad syntax

1
If process-body is intended to consume a list of syntaxes, then you can probably do something like: (process-body (syntax->list #'(body ...))), using syntax->list to fragment the syntax object into its pieces.dyoo
Without knowing more information about what process-body does, the question is a little unclear. Can you add more detail?dyoo
Sure thing, I edited it. Let me know if that makes a bit more sense. I also did try the (syntax->list), but then not sure how to return the cdr of the list as standalone syntax objects from the helper.Scott Klarenbach
If I understand the problem correctly: can you use begin to splice?dyoo
it's the splicing i'm not familiar with. So, let's say process-body receives a list of stx-objects. Currently, it just receives one syntax object and returns it as (lambda () (something) stx-obj (something-else)). What I'd like to do is basically (apply begin stx-list), but that doesn't workScott Klarenbach

1 Answers

4
votes

The left hand side of a with-syntax pattern can also have ellipses, so that the following is possible:

(define-syntax (test stx)
  (syntax-case stx ()
    [(_ body ...)
     (with-syntax ([(body0 ...) (process-body #'(body ...))])
       #'(begin body0 ...))]))

The basic idea is that if process-body returns the transformed body elements, we can then introduce them all together with a begin.


Your process-body definition can also use with-syntax with ellipses too. So you can do something like this:

(define-for-syntax (process-body bodies)
  (with-syntax ([(body ...) bodies])
    (syntax/loc bodies
      (λ (request)
         body ...))))

If that's the definition of process-body, we should amend test since the shape of the result from process-body is now a complete lambda expression, so we can just return its result directly:

(define-syntax (test stx)
  (syntax-case stx ()
    [(_ body ...)
     (process-body (syntax/loc stx (body ...)))]))

As a self-contained example:

#lang racket

(define-syntax (test stx)
  (syntax-case stx ()
    [(_ body ...)
     (process-body 
      (syntax/loc stx (body ...)))]))

(define-for-syntax (process-body bodies)
  (with-syntax ([(body ...) bodies])
    (syntax/loc bodies
      (λ (request)
        (printf "before the body\n")
        body ...
        (printf "after the body\n")))))


;; Let's try it:    
(define p 
  (test (displayln "hello") (displayln "world")))

(p 'should-be-a-request)