【问题标题】:looking for a really simple racket macro example寻找一个非常简单的球拍宏示例
【发布时间】:2026-01-30 11:05:02
【问题描述】:

我这样做了:

#lang racket

(define-syntax-rule (macro-expansion-seconds)
  (current-seconds))

这是做什么的

> (macro-expansion-seconds)
1639244531
> (macro-expansion-seconds)
1639244532
> (macro-expansion-seconds)
1639244533

它在扩展时将(macro-expandsion-seconds) 替换为(current-seconds),并且每次仍然评估该表单。

但是如何让它在扩展时评估(current-seconds),然后执行此操作?

> (macro-expansion-seconds)
1639244533
> (macro-expansion-seconds)
1639244533
> (macro-expansion-seconds)
1639244533

我知道在这种情况下我可以这样做

(define macro-expansion-seconds
  (current-seconds))

还有这个

> macro-expansion-seconds
1639244766
> macro-expansion-seconds
1639244766
> macro-expansion-seconds
1639244766

(名称不再有意义)

但我试图弄清楚宏是如何工作的,并认为这是一个简单的例子,可以帮助我找出更难的例子。

【问题讨论】:

    标签: racket lisp-macros


    【解决方案1】:

    最简单的方法是:

    #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)
    

    这里begin-for-syntax 告诉扩展器以下表达式将在编译时进行计算。因此the-time 的值将是一个数字。然后宏需要将数字(这是一个数据)转换为一段语法。这是datum->syntax 的工作。

    【讨论】:

    • 如果可以问一个子问题...我怎样才能看到展开的宏?
    • 其实我只是问一个问题。