我正在方案实现中实现卫生宏,我刚刚实现了syntax-rules,但我有以下代码:
(define odd?
(syntax-rules ()
((_ x) (not (even? x)))))这与此之间应该有什么区别:
(define-syntax odd?
(syntax-rules ()
((_ x) (not (even? x)))))据我所知,syntax-rules只是返回语法转换器,为什么不能仅仅使用define将其分配给符号呢?为什么我需要使用define-syntax?这句话还能做些什么?
首先也应该在计划中工作吗?还是只有第二个?
另外,let对let-syntax和letrec与letrec-syntax的区别是什么?如果值是语法转换器,那么(define|let|letrec)-syntax应该只进行类型检查吗?
编辑
我有这个实现,仍然使用lisp宏:
;; -----------------------------------------------------------------------------
(define-macro (let-syntax vars . body)
`(let ,vars
,@(map (lambda (rule)
`(typecheck "let-syntax" ,(car rule) "syntax"))
vars)
,@body))
;; -----------------------------------------------------------------------------
(define-macro (letrec-syntax vars . body)
`(letrec ,vars
,@(map (lambda (rule)
`(typecheck "letrec-syntax" ,(car rule) "syntax"))
vars)
,@body))
;; -----------------------------------------------------------------------------
(define-macro (define-syntax name expr)
(let ((expr-name (gensym)))
`(define ,name
(let ((,expr-name ,expr))
(typecheck "define-syntax" ,expr-name "syntax")
,expr-name))))这个代码是对的吗?
这个代码能起作用吗?
(let ((let (lambda (x) x)))
(let-syntax ((odd? (syntax-rules ()
((_ x) (not (even? x))))))
(odd? 11)))发布于 2020-04-12 16:34:53
这个问题似乎意味着对宏有一些深层次的混淆。
让我们设想一种语言,其中syntax-rules返回一些语法转换器函数(我不确定这在RnRS方案中是正确的,我认为在Racket中是正确的),并且let和let-syntax是相同的。
因此,让我们编写这个函数:
(define (f v)
(let ([g v])
(g e (i 10)
(if (= i 0)
i
(e (- i 1))))))当然,我们可以转化为:
(define (f v n)
(v e (i n)
(if (<= i 0)
i
(e (- i 1)))))此外,我还将告诉您,在环境中不存在对e或i的绑定。
解释器与这个定义有什么关系?它能编译吗?它是否可以安全地推断i不可能有任何意义,因为它被用作一个函数,然后作为一个数字?它能安全地做任何事情吗?
答案是,不,它不能。直到它知道函数的参数是什么,它不能做任何事情。这意味着,每次调用f时,它都必须再次做出决定。特别是,v可能是:
(syntax-rules ()
[(_ name (var init) form ...)
(letrec ([name (λ (var)
form ...)])
(name init))]))在这个定义下,f的定义是有意义的。
事情变得更糟:更糟。这个怎么样?
(define (f v1 v2 n)
(let ([v v1])
(v e (i n)
...
(set! v (if (eq? v v1) v2 v1))
...)))这意味着,像这样的系统不知道它要解释的代码意味着什么,直到解释它的那一刻,甚至是在这一点之后,正如您从上面的第二个函数中可以看到的那样。
因此,Lisps没有做这种可怕的事情,而是做了一些明智的事情:他们将代码的评估过程分成几个阶段,每个阶段在概念上都发生在下一个阶段之前。
下面是一些想象中的Lisp的序列(这有点接近CL的功能,因为我大部分的知识都是这样的,但它并不打算代表任何特定的系统):
在这个阶段,代码可能在用户定义的code;
)。
对于每个代码单元,这些阶段按顺序进行,每个阶段在下一个阶段开始之前完成。
这意味着用户可以干预的每个阶段都需要自己的一组定义和绑定表单:例如,可以说“这个东西控制了第二阶段发生的事情”。
这就是define-syntax、let-syntax &c所做的:他们说“这些绑定和定义控制着第二阶段发生的事情”。例如,您不能使用define或let来这样做,因为在第2阶段,这些操作还没有意义:它们只在第3阶段获得意义(可能本身是扩展到某些原始事物的宏)。在第2阶段,它们只是宏正在吞食和吐出的语法的一部分。
https://stackoverflow.com/questions/61163571
复制相似问题