Chr*_*oks 3 lambda scheme racket
说我有这个代码:
#lang racket
(define a
((? (x) x)
((? (y) y)
(? (z)
((? (w) w) z)))))
Run Code Online (Sandbox Code Playgroud)
我直观地知道这个lambda表达式(扩展性地)等于 (? (z) z)
我的问题是,如果a我想看看Racket在内部简化了多少功能,是否有办法打印出来.
更多信息:
默认情况下,如果我输入a解释器,我得到#<procedure:y>(这似乎提示了评估发生了多少).我可以将输出样式更改为"构造函数",然后结果是(lambda (a1) ...)更接近我想要的结果,但我仍然不知道正文中哪些是重要的部分.
我想有人可以通过对Racket的评估策略有更全面的了解来回答这个问题,但是如果显示程序主体是一件可能发生的事情,我仍然感兴趣.
通常,在运行时无法查看闭包的主体."body"是源代码的一部分.它被编译成字节码(稍后由JIT编译成机器代码).闭包在运行时包含正文中自由变量的捕获值和指向代码的指针.
也就是说,你可能会对研究expand或的输出感到满意compile.
现在expand只扩展语法,因此您将无法看到任何优化:
> (expand-syntax #'(define a
((? (x) x)
((? (y) y)
(? (z)
((? (w) w) z))))))
(define-values (a)
(#%app (lambda (x) x)
(#%app (lambda (y) y)
(lambda (z)
(#%app (lambda (w) w) z)))))
Run Code Online (Sandbox Code Playgroud)
请注意,这#%app意味着"申请".
要在应用优化后查看结果,我们需要调用编译器.内置compile生成字节码,因此我们使用compile-zo它将字节码转换为表示字节码的结构(并且它们在repl中很好地打印).
> (compile-zo '((? (x) x)
((? (y) y)
(? (z)
((? (w) w) z)))))
'#s((compilation-top zo 0)
1
#s((prefix zo 0) 0 () ())
#s((application expr 0 form 0 zo 0)
#s((closure expr 0 form 0 zo 0)
#s((lam expr 0 form 0 zo 0)
()
(preserves-marks single-result)
1
(val)
#f
#()
()
#f
6
#s((localref expr 0 form 0 zo 0) #f 0 #f #f #f))
closure64862)
(#s((closure expr 0 form 0 zo 0)
#s((lam expr 0 form 0 zo 0)
y
(preserves-marks single-result)
1
(val)
#f
#()
()
#f
6
#s((localref expr 0 form 0 zo 0) #f 0 #f #f #f))
y64863))))
Run Code Online (Sandbox Code Playgroud)
只剩下一个应用程序,因此在编译期间确实简化了程序.
有关的定义,请参阅https://github.com/soegaard/meta/blob/master/runtime/racket-eval.rktcompile-zo.
最后,另一个选择是查看JIT生成的机器代码.请参阅https://github.com/samth/disassemble
UPDATE
如果我正确读取字节码,它对应于:
((? (x) x)
(? (y) y))
Run Code Online (Sandbox Code Playgroud)