什么是"3D语法"?

Gre*_*ott 8 macros racket

在编写Racket宏的过程中,"3D语法"是什么意思?

我已经听过几次这句话了.包括一次参考写的宏.但那是一段时间以前; 我修好了,现在我不记得我到底做错了什么.

另外:3D语法总是坏的吗?或者是它eval(如果你认为你需要使用它,你可能错了,但在专家手中有一些有效的用途)?

dyo*_*yoo 7

语法对象通常应该只是可序列化的数据.3D语法削弱了这种条件:它允许我们潜入任意值,而不仅仅是普通数据.这就是使它们变成"3d"的原因:它们的价值高于你期望的语法对象.

例如,我们可以潜入lambda价值观!

#lang racket

(define ns (make-base-namespace))
(define (set-next! n)
  (parameterize ([current-namespace ns])
    (eval #`(define next #,n))))    ;; <--  3d-syntax here

(define (compute s)
  (parameterize ([current-namespace ns])
    (eval s)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define counter 0)
(set-next! (lambda ()
             (set! counter (add1 counter))
             counter))

(compute '(+ (next)
             (next)
             (next)
             (next)))
Run Code Online (Sandbox Code Playgroud)

这样做通常是件坏事,因为这些值的存在可能意味着在编译阶段泄漏信息的无根据的尝试.结果是可能无法单独编译的结果.如果您看到一个类似于以下内容的错误:

write: cannot marshal value that is embedded in compiled code value
Run Code Online (Sandbox Code Playgroud)

然后,这很可能是由于宏生成了一段无法序列化为字节码的3d语法.

有时候,在极少数情况下,我们确实需要3d语法,通常是在动态评估环境中.作为一个具体的例子,DrRacket中的调试器可能想要注释程序的语法,以便函数应用程序直接调用回调试器的函数,以便我们可以在程序编辑器中执行交互式代码覆盖着色等操作.从这个意义上讲,3d语法可以充当动态评估代码与其周围环境之间的通信通道.

  • 首先谢谢你的回答!我一直在重新阅读、思考并试图了解您的答案。一方面,我认为答案需要讨论语法转换器,但您使用的是 eval 和命名空间,我正在尝试思考这意味着什么。此外,我对示例中使用名称空间感到困惑和/或分心,并试图了解这是否必不可少,如果是,如何/为什么。[这个](https://gist.github.com/greghendershott/5923364) 更简单。它给出了相同的答案: 10. 它是等价的还是不等价的? (2认同)
  • 每当我使用 `eval` 时,我都会假装就 `eval` 而言一切都是“自由变量”,并且我使用命名空间来确切地知道这些自由变量是如何被解析的。我尽量不要在没有明确说明或不知道命名空间应该是什么的情况下使用 `eval`,否则我相信我的调用者会为我设置这些绑定。由于我通常无法控制谁给我打电话,我想解决任何歧义,这就是为什么存在“当前命名空间”的原因。 (2认同)