Reputation: 259
I am using syntax transformers to define macros in Racket. I want to create some helper functions to help me manipulate the syntax. However, the functions I defined outside the syntax transformer are not available inside the syntax transformer. For example, in the following code
(define (my-function x) (+ x 1))
(define-syntax my-macro
(lambda (stx)
(datum->syntax stx (my-function (cadr (syntax->datum stx))))))
I got the error "my-function: reference to an unbound identifier at phase: 1; the transformer environment".
After some searching, I am able to write the following code so that my-function
is available inside the syntax transformer.
(begin-for-syntax
(define (my-function x) (+ x 1)))
(provide (for-syntax my-function))
(define-syntax my-macro
(lambda (stx)
(datum->syntax stx (my-function (cadr (syntax->datum stx))))))
But the problem is, my-function
is not available outside the syntax transformer this time. Sometimes I want to check those helper functions in ordinary code, so I need to be able to call it from both inside and outside the syntax transformer, just like the function cadr
. How can I achieve that?
I know my question has something to do with Racket's syntax model, in particular the concept of "phase level", but I never really understand it. If you could provide some easy-to-follow tutorials explaining it I would even be more grateful.
Upvotes: 2
Views: 180
Reputation: 6502
A common way is to define your function that you want to share across phases in another (sub)module. Then, require
it twice.
#lang racket
(module common racket
(provide my-function)
(define (my-function x) (+ x 1)))
(require 'common
(for-syntax 'common))
(define-syntax my-macro
(lambda (stx)
(datum->syntax stx (my-function (cadr (syntax->datum stx))))))
(my-function 1)
(my-macro 123)
Upvotes: 6