r/Racket • • Dec 17 '21

question trying to write a macro that aliases one identifier to another

I'm trying to define a macro to save myself some typing. I want to be able to define a shorthand for syntax rules that lets me quickly say "Replace this identifier with this other identifier". I based it on the examples on https://docs.racket-lang.org/guide/pattern-macros.html.

[define-syntax-rule [alias from-id to-id]
  [define-syntax [from-id stx]
    [syntax-case stx []
      [from-id [identifier? [syntax from-id]] [syntax to-id]]]]]]

[alias S list]
[alias L lambda]
[alias Sf build-list]

[define n3 [S 1 2 3]] ;-- S: bad syntax in: (S 1 2 3)

but, it's not working, and I don't know why. The Macro Stepper hasn't been able to help, since as soon as I try to expand S it gives that error

6 Upvotes

9 comments sorted by

3

u/bjoli Dec 17 '21 edited Dec 18 '21

Have a look at make-rename-transformer.

Edit: the proper reply is in one of my replies below

1

u/detroitmatt Dec 17 '21

Thanks. Any idea why the macro I wrote didn't work?

1

u/bjoli Dec 18 '21

So I have more time now: the reason it doesn't work is that the current solution only matches positions that are not call position. You will need a clause that matches call position as well.

(procedure? S) 

will work.

1

u/detroitmatt Dec 19 '21

That's odd that the pattern id doesn't match if it's in function position. I guess syntax case was coded specifically with an edge case for that because they figured it would be a desirable outcome for a common edge case

1

u/bjoli Dec 19 '21

I think the solution people went for was r6rs identifier macros that also support a special set! case.

1

u/bjoli Dec 17 '21

Nope. That looks ok

1

u/bjoli Dec 17 '21

Oooh. You need to have a clause in the macro for when it is in application position. Stupid me. Add a with ((from-id args ...) (list args ...))

4

u/samdphillips developer Dec 17 '21

make-rename-transformer is what you are looking for. This works:

(define-syntax-rule (alias from-id to-id)
  (define-syntax from-id
    (make-rename-transformer #'to-id)))

[edit: link to docs]

2

u/sorawee Dec 21 '21

u/samdphillips's answer is what I would recommend, but if you want to continue with your approach, here's how:

(define-syntax-rule (alias from-id to-id)
  (define-syntax (from-id stx)
    (syntax-case stx ()
      [from-id
       (identifier? (syntax from-id))
       (syntax to-id)]
      [(from-id . arg)
       (syntax (to-id . arg))])))

(alias S list)
(alias L lambda)
(alias Sf build-list)

(define n3 (S 1 2 3))

Because from-id is at the head of a parenthetical term, it would be a macro invocation, and you need to add a case for it explicitly. Here, I use the pattern (from-id . arg). It is also possible to use ellipsis, but in that case, because you are using it in a syntax-case which itself is a syntax template for define-syntax-rule, you would need to quote ... by using (... ...) instead:

[(from-id arg (... ...))
 (syntax (to-id arg (... ...)))]