这是此 QA 答案的一个后续问题。我使用 Racket v8.16。
来自doc1:compile_time_instantiation.rkt
(module compile-time-number racket/base
(require (for-syntax racket/base))
(begin-for-syntax
(printf "picked ~a\n" (random)))
(printf "running\n"))
然后:
$ racket -i -e '(dynamic-require "compile_time_instantiation.rkt" #f)'
Welcome to Racket v8.16 [cs].
picked 0.015421409441077423
running
$ racket -i -e '(require "compile_time_instantiation.rkt")'
Welcome to Racket v8.16 [cs].
picked 0.14007121863188537
running
picked 0.7200261945290138
$ racket -i
Welcome to Racket v8.16 [cs].
> (require "compile_time_instantiation.rkt")
picked 0.7451208846143317
running
$ racket compile_time_instantiation.rkt
picked 0.9883107842338839
running
doc1 说:
同时, dynamic-require 仅实例化一个模块;它不访问模块。这种简化就是为什么前面的一些示例使用 dynamic-require而不是 require 的原因。
当一个模块被实例化时,它主体中的运行时表达式会被评估。
因此,第二条命令中的额外“picked ...”来自require
扩展后的额外访问:
当访问一个模块时,其主体中的编译时表达式(例如宏定义)会被评估。
当模块被扩展时,它就会被访问。
通过访问评估的模块编译时表达式包括定义语法形式的右侧和开始语法形式的主体。
但为什么第三个没有呢?