💾 Archived View for idiomdrottning.org › define-ir-syntax captured on 2021-12-03 at 14:04:38. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

define-ir-syntax

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.

Bonus Episode! 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.

Update: 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.