Racket模块宏生成的语法对象中绑定机制的疑问
关于《Beautiful Racket》Stacker教程中宏绑定机制的疑问
我完成了《Beautiful Racket》一书中的Stacker教程,该教程演示了如何用Racket实现一个简单的栈式计算器迷你语言。完成教程后,我仍对其工作原理存疑,尤其是宏中的绑定机制。
定义Stacker语言的代码(stacker.rkt)
#lang br/quicklang (define (read-syntax path port) (define src-lines (port->lines port)) (define src-datums (format-datums '(handle ~a) src-lines)) (define module-datum `(module stacker-mod "stacker.rkt" ,@src-datums)) (datum->syntax #f module-datum)) (provide read-syntax) (define-macro (stacker-module-begin HANDLE_EXPR ...) #'(#%module-begin HANDLE_EXPR ... (display (first stack)))) (provide (rename-out [stacker-module-begin #%module-begin])) (define stack empty) (define (pop-stack!) (define arg (first stack)) (set! stack (rest stack)) arg) (define (push-stack! arg) (set! stack (cons arg stack))) (define (handle [arg #f]) (cond [(number? arg) (push-stack! arg)] [(or (equal? + arg) (equal? * arg)) (define op-result (arg (pop-stack!) (pop-stack!))) (push-stack! op-result)])) (provide handle) (provide + *)
Stacker语言的测试代码(stacker-test.rkt)
#lang reader "stacker.rkt" 4 8 + 3 *
运行stacker-test.rkt后,控制台会输出整数36,也就是(4+8)*3的计算结果。
我理解的运行流程
- Racket识别到
#lang reader "stacker.rkt",从stacker.rkt中找到read-syntax函数并传入文件读取端口。 read-syntax读取文件内容,将每一行转换为调用handle函数的 datum(比如'(handle 4)),把这些datum放入表示module的datum中,再转换为语法对象返回。- Racket提取语法对象中的datum,转换为可执行代码并执行。
module函数从stacker.rkt中找到#%module-begin宏(即stacker-module-begin)并调用,传入作为module参数的handledatum。 stacker-module-begin宏创建一个语法对象,该对象对应的代码执行时会调用br/quicklang中的#%module-begin宏,传入原handle表达式及显示stack栈顶元素的表达式,然后返回该语法对象。- Racket执行该语法对象对应的代码,最终实际执行以下代码:
handle(4) handle(8) handle(+) handle(3) handle(*) (display (first stack))
我的疑问
执行上述代码时,Racket是如何识别handle和stack的绑定的?我有两种猜想:
stacker-module-begin创建语法对象时,将文件中后续定义的handle和stack的绑定作为语法对象上下文的一部分,使Racket在执行时拥有这些绑定。- Racket已执行了整个
stacker.rkt文件,因此在自身上下文中拥有所有导出的定义,与语法对象附带的绑定无关。
我最初倾向于第一种猜想,但这个流程必须在stacker.rkt中包含(provide handle)才能正常工作——如果绑定包含在语法对象中,那根本不需要导出,这让我产生了疑问。
后来我又觉得第二种猜想是对的,但stack从未通过provide导出,那stack的绑定必然是包含在stacker-module-begin创建的语法对象中。既然如此,为什么handle的绑定没有被包含进去?
内容的提问来源于stack exchange,提问作者T Hummus
相关产品推荐
相关产品推荐

