Racket Macro Как передать эллипсы вспомогательной функции?

Дано:

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

Как я должен получить шаблон и эллипсы в помощнике? Я даже не уверен, что обертывание тела ... внутри () правильно, но я видел его повсюду, и это единственное, что не дает сбоев.

Процедура тела процесса заканчивается синтаксисом, который имеет дополнительную () обертку. Я могу попытаться разбить это на части, но мне просто интересно, как правильно это сделать.

process-body оборачивает шаблон тела некоторым кодом до И после. И, как и в случае с определением, я хочу предоставить макросу несколько форм, а не все формы в одном списке. Итак, если задано (форма1) (форма2), где форма2 — многоточие, тело процесса должно (делать-что-то) (форма1) (форма2) (делать-что-то-еще).

ie,

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

Конечно, у меня это работает, когда я определяю шаблон в строке, и я полагаю, что мог бы сделать это здесь, но иногда шаблон становится громоздким, и приятно вызвать помощника.

Большое спасибо.

В качестве редактирования, чтобы попробовать первый пример dyoo, я предоставляю следующее:

#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"))

λ: плохой синтаксис


person Scott Klarenbach    schedule 15.01.2013    source источник
comment
Если process-body предназначен для использования списка синтаксисов, то вы, вероятно, можете сделать что-то вроде: (process-body (syntax->list #'(body ...))), используя syntax->list для фрагментации объекта синтаксиса на его части.   -  person dyoo    schedule 15.01.2013
comment
Не зная больше информации о том, что делает process-body, вопрос немного неясен. Можете ли вы добавить больше деталей?   -  person dyoo    schedule 15.01.2013
comment
Конечно, я отредактировал. Дайте мне знать, если это имеет смысл. Я также попробовал (syntax-›list), но тогда не знал, как вернуть cdr списка как автономные объекты синтаксиса из помощника.   -  person Scott Klarenbach    schedule 15.01.2013
comment
Если я правильно понимаю задачу: можно ли использовать begin для сплайсинга?   -  person dyoo    schedule 15.01.2013
comment
это сплайсинг, с которым я не знаком. Итак, допустим, process-body получает список stx-объектов. В настоящее время он просто получает один синтаксический объект и возвращает его как (лямбда() (что-то) stx-obj (что-то еще)). То, что я хотел бы сделать, это в основном (применить начало stx-list), но это не работает   -  person Scott Klarenbach    schedule 15.01.2013


Ответы (1)


Левая сторона шаблона with-syntax также может иметь эллипсы, так что возможно следующее:

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

Основная идея заключается в том, что если process-body возвращает преобразованные элементы тела, мы можем представить их все вместе с begin.


Ваше определение process-body также может использовать with-syntax с многоточием. Итак, вы можете сделать что-то вроде этого:

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

Если это определение process-body, мы должны изменить test, так как форма результата из process-body теперь является полным лямбда-выражением, поэтому мы можем просто вернуть его результат напрямую:

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

В качестве самостоятельного примера:

#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)
person dyoo    schedule 15.01.2013
comment
Хорошо, это сработало. Я не понимал, что эллипсы могут входить в назначение with-синтаксиса таким образом. Я пытался вернуть его как body0, но потом он жаловался, что в шаблоне нет многоточия. - person Scott Klarenbach; 15.01.2013
comment
За исключением того, что при заключении в лямбду я получаю лямбда: плохой синтаксис. Итак, если тело процесса (см. Конец вопроса для редактирования). Это связано с тем, что круглые скобки заключают #'(тело...) при передаче, я думаю?? - person Scott Klarenbach; 15.01.2013
comment
По сути, происходит то, что окончательное возвращаемое значение (лямбда (лямбда (запрос) ((мой-прок)) с двумя круглыми скобками, поскольку исходный синтаксис был заключен в круглые скобки, чтобы передать #'body... как один аргумент. Хотя я не уверен, мозг начинает заедать ;) - person Scott Klarenbach; 15.01.2013
comment
Без проблем. Дайте мне знать, если пересмотренный ответ поможет. Также обратите внимание на учебник Грега Хендершотта под названием Fear of Macros. greghendershott.com/fear-of-macros - person dyoo; 15.01.2013
comment
Та же проблема, с вашими правками. λ: плохой синтаксис. Формы test и process-body идентичны вашим, за исключением того, что (syntax/loc body-syntax теперь заменен на (syntax/loc bodys - person Scott Klarenbach; 15.01.2013
comment
Если я полностью уберу эллипсы, это, конечно, сработает. И разница в том, что при обертывании #'body ... внутри () эти дополнительные скобки заканчиваются в конечном синтаксисе, что приводит к (lamda (результат) ((сделать что-то) (сделать что-то n+1)) - person Scott Klarenbach; 15.01.2013
comment
Я включаю самодостаточный ответ; посмотрите, есть ли смысл. Я до сих пор понятия не имею, где вы могли бы увидеть ошибку, которую вы видите, если бы λ не обрабатывался отдельно, а не во главе формы в скобках, или если бы вы строили λ без списка переменных, как один из ваших предыдущие комментарии предполагают. То есть (lambda (lambda (request) ((my-proc))) выглядит неправильно: я ожидал (lambda (request) (my-proc)) или что-то в этом роде: там слишком много lambda... :) - person dyoo; 15.01.2013
comment
Не уверен, вероятно, это простая ошибка из-за целого дня кодирования новичка в рэкете. Я добавил исходный вопрос с моим собственным автономным примером, который терпит неудачу. - person Scott Klarenbach; 15.01.2013
comment
Посмотрите внимательнее на мое определение test и обратите внимание, что оно больше не вводит begin. Ошибка в том, что test2 в основном создает объект синтаксиса: #'(begin λ (request) (print "hi")). - person dyoo; 15.01.2013
comment
давайте продолжим это обсуждение в чате - person dyoo; 15.01.2013