Macro-defining macro in Racket?
Asked Answered
U

3

7

In Common Lisp it is relatively easy to create a macro-defining macro. For example, the following macro

(defmacro abbrev (short long)
  `(defmacro ,short (&rest args)
     `(,',long ,@args)))

is a macro-defining macro, because it expands to another macro.

If we now put

(abbrev def defun) 

in our program, we can write def instead of defun whenever we define a new function. Of course, abbrev can be used for other things, too. For example, after

(abbrev /. lambda)

we can write (/. (x) (+ x 1)) instead of (lambda (x) (+ x 1)). Nice. (For detailed explanation of abbrev, see http://dunsmor.com/lisp/onlisp/onlisp_20.html)

Now, my questions are:

  1. Can I write the macro-defining macros in Racket?
  2. If I can, how to do that? (for example, how to write something similar to abbrev macro in Racket?)
Ultrasonic answered 27/10, 2014 at 21:15 Comment(2)
You inverted your macro parameters, long should come first.Prosaism
I corrected that in my question. Tanks!Ultrasonic
P
9

According to this part of the Racket Guide:

(define-syntax-rule (abbrev short long)
  (define-syntax-rule (short body (... ...))
    (long body (... ...))))

Quoting the above link:

The only non-obvious part of its definition is the (... ...), which “quotes” ... so that it takes its usual role in the generated macro, instead of the generating macro.

Now

(abbrev def define)
(abbrev /. lambda) 
(def f (/. (x) (+ x 1)))
(f 3)  

yields

4

FWIW, it works on Guile as well, so it's no Racket-specific thing.

Prosaism answered 27/10, 2014 at 21:39 Comment(0)
O
5

ad 1. Yes. ad 2. Your example can most easily be written

#lang racket

(define-syntax (abbrev stx)
  (syntax-case stx ()
    [(_ short long)
     #'(define-syntax short (make-rename-transformer #'long))]))

(abbrev def define)
(def x 42)
x

The example above evaluates to 42.

Osteoclasis answered 27/10, 2014 at 21:38 Comment(2)
The 'new' term is creating confusion here ('short' is actually new term). It will be clearer if 'long' is used (instead of 'new') as in other places on this page.Humour
I agree. I have changed it.Osteoclasis
H
0

I find that renaming can be done simply with define or let statements:

(define =? =)
(define lr list-ref)

or:

(let ((=? =)
      (lr list-ref))
  (println (lr '(1 2 3) 2))
  (println (=? 1 2))
  (println (=? 1 1)))

Output:

3
#f
#t

There seem to be no need for any macro for this purpose.

Humour answered 18/10, 2016 at 2:30 Comment(2)
That doesn't work when you want to rename a special form or a macro like define or lambdaThermo
What works then is (define-syntax def (make-rename-transformer #'define)) or (define-syntax /. (make-rename-transformer #'lambda))Thermo

© 2022 - 2024 — McMap. All rights reserved.