我一直在阅读https://lispcast.com/when-to-use-a-macro,它指出(关于clojure的宏)
另一个示例是在编译时作为优化来执行昂贵的计算
我抬起头,似乎clojure的宏不卫生。这也可以适用于卫生的吗?特别是谈论Scheme。据我了解,卫生宏只能转换语法,但是无论如何,代码的实际执行都将推迟到运行时。
答案 0 :(得分:1)
是的。 Macro hygiene仅指宏扩展是否可以意外捕获标识符。不管宏是否卫生,在编译时都会进行常规的宏扩展(与读取器宏扩展相对)。宏扩展将宏的代码替换为正在执行的结果。它们的两个主要用例是转换语法(即DSL),通过消除运行时或同时消除两者的计算来提高性能。
想到一些例子:
您还可以结合示例并使用一个备忘的SQL解析器。几乎所有在编译时都具有所有必要输入并因此可以计算结果的方案就是一个候选方案。
答案 1 :(得分:0)
是的,卫生宏可以执行此类操作。作为示例,这里是一个在Racket中称为plus
的宏,它类似于+
,不同之处在于,在宏扩展时,它会将相邻文字数字的序列求和。因此,它完成了您可能希望在运行时在宏扩展时(因此有效地在编译时)完成的一些工作。例如,
(plus a b 1 2 3 c 4 5)
扩展到
(+ a b 6 c 9)
有关此宏的一些说明。
syntax-parse
,但我听不懂。+
不同的结果。特别地,+
被定义为从左到右成对添加,而plus
则通常不是这样:特别是所有文字都首先添加了(假设您已经完成(需要球拍/发球,而{{ 1}}&c具有与在我的计算机上相同的值),则+max.0
的值为(+ -max.0 1.7976931348623157e+308 1.7976931348623157e+308)
,而1.7976931348623157e+308
的值为(plus -max.0 1.7976931348623157e+308 1.7976931348623157e+308)
,因为首先添加两个文字,这会溢出。+inf.0
中的最后一个,您可以像+
那样对待它:它可以说{{1 }}(例如,尽管在这种情况下不会进行明智的优化)。这里是:
syntax-case
实际上,甚至可以更加主动地执行此操作,从而将(apply plus ...)
变成(require (for-syntax racket/list))
(define-syntax (plus stx)
(define +/stx (datum->syntax stx +))
(syntax-case stx ()
[(_)
;; return additive identity
#'0]
[(_ a)
;; identity with one argument
#'a]
[(_ a ...)
;; the interesting case: there's more than one argument, so walk over them
;; looking for literal numbers. This is probably overcomplicated and
;; unidiomatic
(let* ([syntaxes (syntax->list #'(a ...))]
[reduced (let rloop ([current (first syntaxes)]
[tail (rest syntaxes)]
[accum '()])
(cond
[(null? tail)
(reverse (cons current accum))]
[(and (number? (syntax-e current))
(number? (syntax-e (first tail))))
(rloop (datum->syntax stx
(+ (syntax-e current)
(syntax-e (first tail))))
(rest tail)
accum)]
[else
(rloop (first tail)
(rest tail)
(cons current accum))]))])
(if (= (length reduced) 1)
(first reduced)
;; make sure the operation is our +
#`(#,+/stx #,@reduced)))]
[_
;; plus on its own is +, but we want our one. I am not sure this is right
+/stx]))
。这可能具有更令人兴奋的可能得到不同答案的含义。值得注意的是CL规范says about this:
对于在数学上是关联的(并且可能是可交换的)函数,一致的实现可以以与关联的(并且可能是可交换的)重排一致的任何方式来处理自变量。这不会影响参数形式的计算顺序。未指定的只是参数值的处理顺序。这意味着应用自动强制的实现方式可能会有所不同。
因此,这样的优化在CL中显然是合法的:我不确定在Racket中是否合法(尽管我认为应该如此)。
(plus a b 1 2 c 3)