From f4b52138f3965bbc7f697e3c92a8f3bfe5085610 Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Tue, 26 Apr 2016 13:23:09 -0700 Subject: [PATCH] add `define-inverting` --- beautiful-racket-lib/br/define.rkt | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/beautiful-racket-lib/br/define.rkt b/beautiful-racket-lib/br/define.rkt index d23c40f..c9c2b22 100644 --- a/beautiful-racket-lib/br/define.rkt +++ b/beautiful-racket-lib/br/define.rkt @@ -197,4 +197,32 @@ (define-syntax-rule (br:define+provide arg ...) - (define+provide arg ...)) + (define+provide arg ...)) + + +(br:define #'(define-inverting (syntax (_id . _patargs)) _syntaxexpr) + #'(define-syntax (_id stx) + (let () + (define (expand-macro mac) + (syntax-disarm (local-expand mac 'expression #f) #f)) + (syntax-case stx () + [(_ . rest) + (with-syntax ([_patargs (map expand-macro (syntax->list #'rest))]) + _syntaxexpr)])))) + +(module+ test + ;; an inverting macro expands its arguments. + ;; so `foo` does not get `(falsy a) (falsy b) (falsy c)` as arguments, + ;; but rather the result of their expansion, namely `((#f a) (#f b) (#f c))` + ;; and `tree` does not get `(foo (#f a) (#f b) (#f c))` as its first argument, + ;; but rather the result of its expansion, namely (a b c). + (define-inverting #'(tree (_id ...) _vals) + #'(let () + (define-values (_id ...) _vals) + (list _id ...))) + + (define-inverting #'(foo (#f _id) ...) #'(_id ...)) + + (define-syntax-rule (falsy id) (#f id)) + + (check-equal? (tree (foo (falsy a) (falsy b) (falsy c)) (values 1 2 3)) '(1 2 3))) \ No newline at end of file