Вы можете сделать это с помощью вспомогательного макроса, который перебирает каждый "arg-or-arg + type" и преобразует их в (arg type)
для согласованности.
Во-первых, я рекомендую определить базовую версию макрос, который работает только с последовательной (arg type)
версией вещей:
(define-syntax define/custom-core
(syntax-rules ()
((_ (name (arg type) ...) body ...)
; among other things
(define (name arg ...) body ...))))
Затем вы можете определить вспомогательный макрос, который имеет дело с двумя списками входных аргументов: один для согласованных (arg type)
вещей, а другой для вещи типа "arg-or-arg +". Пример использования может выглядеть так:
(define/custom-helper (name ((arg type) ...) (arg-or-arg+type ...)) body ...)
По мере прохождения через arg-or-arg+type ...
они перемещаются в список (arg type) ...
. Когда arg-or-arg+type ...
пусто, это делается и все элементы (arg type)
помещаются в вызов define/custom-core
.
(define-syntax define/custom-helper
(syntax-rules ()
((_ (name (arg+type ...) ()) body ...)
(define/custom-core (name arg+type ...) body ...))
((_ (name (arg+type ...) ((arg type) . rest)) body ...)
(define/custom-helper (name (arg+type ... (arg type)) rest) body ...))
((_ (name (arg+type ...) (arg . rest)) body ...)
(define/custom-helper (name (arg+type ... (arg any)) rest) body ...))))
Это зависит от того, что arg
эквивалентно (arg any)
.
Затем все, что осталось - это обращенный наружу макрос define/custom
для вызова вспомогательного макроса. Он может передавать пустой список arg+type
и передавать аргументы в место arg-or-arg+type
, чтобы помощник имел дело с ним.
(define-syntax define/custom
(syntax-rules ()
((_ (name arg-or-arg+type ...) body ...)
(define/custom-helper (name () (arg-or-arg+type ...)) body ...))))