I did this:
#lang racket
(define-syntax-rule (macro-expansion-seconds)
(current-seconds))
which does this
> (macro-expansion-seconds)
1639244531
> (macro-expansion-seconds)
1639244532
> (macro-expansion-seconds)
1639244533
It replaces (macro-expandsion-seconds)
with (current-seconds)
at expansion time, and still evaluates that form each time.
But how do I make it evaluate (current-seconds)
at expansion time, and then do this?
> (macro-expansion-seconds)
1639244533
> (macro-expansion-seconds)
1639244533
> (macro-expansion-seconds)
1639244533
I know in this case I could just do this
(define macro-expansion-seconds
(current-seconds))
and this
> macro-expansion-seconds
1639244766
> macro-expansion-seconds
1639244766
> macro-expansion-seconds
1639244766
(name no longer makes sense)
but I am trying to figure out how macros work, and thought this would be an easy example that could help me figure out harder ones.
The simplest way would be:
#lang racket
(begin-for-syntax
(define the-time (current-seconds)))
(define-syntax (macro-expansion-seconds stx)
(datum->syntax stx the-time))
(macro-expansion-seconds)
(macro-expansion-seconds)
(macro-expansion-seconds)
Here begin-for-syntax
tells the expander that the following expressions are to be evaluated at compile time. Thus the value of the-time
will be a number. The macro then needs to turn the number (which is a datum) into a piece of syntax. That's the job of datum->syntax
.