4

How does one create aliases for macros in Scheme?

in the same vein as this for Clojure

define a synonym for a Clojure macro

and this for Common Lisp

common lisp function/macro aliases

I realize for functions it is

(define alias function)

but I can't seem to find, or come up with, how to define aliases for macros (in GNU Guile to be precise)

Kyuvi
  • 360
  • 3
  • 13

3 Answers3

4

If you are using a scheme implementation which supports R6RS, such as Chez Scheme or guile, the simplest approach is to use identifier-syntax to create an alias:

(define-syntax new-name (identifier-syntax old-name))

identifier-syntax can do more than alias a name: it can alias an expression. So you could define an **unspecified** macro as follows:

(define-syntax **unspecified** (identifier-syntax (if #f #f)))
Chris Vine
  • 677
  • 3
  • 7
2

Guile supports syntax-rules, so a plausible way to create an alias for, say, `and' would look like this:

;; define my-and as an alias for and:
(define-syntax my-and   
  (syntax-rules ()
    [(_ arg ...)
     (and arg ...)]))

;; try it out:
(display (my-and #t #t)) (newline)
(display (my-and #t #f)) (newline)
(display (my-and #f (/ 1 0))) (newline)

If you really wanted a syntax-alias form, you could... surprise! ... define that as a macro:

;; define a 'syntax-alias' form
(define-syntax syntax-alias
  (syntax-rules ()
    [(_ newname oldname)
     (define-syntax newname
       (syntax-rules ()
         [(_ arg (... ...))
          (oldname arg (... ...))]))]))

;; use 'syntax-alias' to define 'my-and' as an alias for 'and':
(syntax-alias my-and and)

;; try it out:
(display (my-and #t #t)) (newline)
(display (my-and #t #f)) (newline)
(display (my-and #f (/ 1 0))) (newline)
John Clements
  • 16,895
  • 3
  • 37
  • 52
  • 1
    Your solution is elegant and probably solves the OP problem. One should also note, however, that you are defining *new* macros, not true *aliases* (i.e. new “names” “referring” to old macros). – Renzo Feb 04 '18 at 07:59
  • I'm definitely defining a macro. My guess is that there's no good language-level definition of what a "true alias" is, though... – John Clements Feb 05 '18 at 03:38
2

In portable Scheme from R5RS you need to make a macro that implements it:

(define-syntax test 
  (syntax-rules ()
    ((_ . args) (if . args))))

It's a little verbose so you can make a macro that does this for you:

(define-syntax define-syntax-alias
  (syntax-rules ()
    ((_ new-name old-name)
     (define-syntax new-name
       (syntax-rules ()
         ((_ . args) (old-name . args)))))))

(define-syntax-alias test if)

Of course the implementation for define-syntax-alias can be put in its own library and reused everywhere you need it for R6RS and beyond.

In a related dialect Racket which started off as Scheme but now has diverged into it's own lisp language you have something like this in the standard language:

(define-syntax test (make-rename-transformer #'if))
Sylwester
  • 47,942
  • 4
  • 47
  • 79
  • I think it should also be noted that in Racket, the easiest way to rename functions and macros is to use `(require (rename-in ....))`. For the above example for aliasing `if` with `test`, it would be `(require (rename-in racket/base (if test))`. – Kyuvi Jun 26 '20 at 14:41
  • @DiiP That works for a whole file, but a rename-transformer is something you could use locally. Eg. in Greg's [Fear of Macros he uses it in `aif`](https://www.greghendershott.com/fear-of-macros/Syntax_parameters.html) and you cannot replace that with an import. – Sylwester Jun 27 '20 at 00:55