Search code examples
racketlisp-macros

looking for a really simple racket macro example


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.


Solution

  • 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.