Update: Now part of brev-separate.
Part of a future thing I’m daydreaming about for Chicken Scheme but maybe useful already on its own:
(define-syntax define-ir-syntax
(ir-macro-transformer
(lambda (e i c)
`(define-syntax ,(cadr e)
(ir-macro-transformer
(lambda (exp ,(i 'inject) ,(i 'compare))
(let ((,(i 'body) (cdr exp)))
,@(cddr e))))))))
If you’re, like me, nostalgic for the leakiness & brevity of defmacro
,
this might be just the ticket. Here’s an example of how to use it:
(define-ir-syntax aif
`(let ((,(inject 'it) ,(car body)))
(if ,(inject 'it) ,(cadr body) ,(caddr body))))
That’s right. Even the definer of anaphoric macros is itself an
anaphoric macro, implicitly binding body
, inject
, and compare
.
define-syntax-rules
Also, while there is already define-syntax-rule
, here is
define-syntax-rules
for when you have multiple patterns per name.
(define-syntax define-syntax-rules
(syntax-rules ()
((_ name arg ...)
(define-syntax name
(syntax-rules arg ...)))))
That might be a little “not worth it”—only saving a single token and a pair—but I’m just really longing for more brevity.
define-ir-syntax*
I found in practice that I often enough wanna destructure and pattern
match on exp
, rather than inject it. The destructuring-bind
companion to our defmacro, as it were. Let’s add a * variant.
(import-for-syntax matchable)
(define-syntax define-ir-syntax*
(ir-macro-transformer
(lambda (e i c)
(let ((cand (caadr e)))
`(define-syntax ,(if (pair? cand) (car cand) cand)
(ir-macro-transformer
(lambda (exp ,(i 'inject) ,(i 'compare))
(match exp
,@(if (pair? cand) (cdr e) (list (cdr e)))))))))))
So it’s similar to define-syntax-rules except there is no keyword
field but you can inject
and compare
.
With this we can make another version of aif
:
(define-ir-syntax*
(aif test yes no)
`(let ((,(inject 'it) ,test))
(if ,(inject 'it) ,yes ,no)))
For another example, see define-closure
in Fancy defines.