Lisp 你需要做的事情是什么';你用过Scheme宏吗?
许多宏的示例似乎都是关于隐藏lambda的,例如在CL中使用openfile。我正在寻找宏的一些更奇特的用途,特别是在PLT方案中。我想知道什么时候考虑使用宏和使用函数。 < P>我将开始回答最后一个问题。何时使用宏而不是函数。宏做了函数做不到的事情,函数做了宏做不到的事情,所以很难将它们混合在一起,但让我们更深入一点 要计算参数时使用函数,要取消计算参数时使用宏。那不是很有用,是吗?当你想用不同的方式写东西,当你看到一个模式,你想抽象时,你可以使用宏。例如:我为不同的foo值定义了三个名为foo create、foo process和foo destroy的函数,其中只有foo的变化。有一个模式,但是对于一个函数来说级别太高了,所以您创建了一个宏Lisp 你需要做的事情是什么';你用过Scheme宏吗?,lisp,scheme,macros,racket,Lisp,Scheme,Macros,Racket,许多宏的示例似乎都是关于隐藏lambda的,例如在CL中使用openfile。我正在寻找宏的一些更奇特的用途,特别是在PLT方案中。我想知道什么时候考虑使用宏和使用函数。 < P>我将开始回答最后一个问题。何时使用宏而不是函数。宏做了函数做不到的事情,函数做了宏做不到的事情,所以很难将它们混合在一起,但让我们更深入一点 要计算参数时使用函数,要取消计算参数时使用宏。那不是很有用,是吗?当你想用不同的方式写东西,当你看到一个模式,你想抽象时,你可以使用宏。例如:我为不同的foo值定义了三个名为fo
根据我的经验,Scheme中的宏与其他Lisp中的宏一样多,比如Common Lisp或。我想这证明了也许卫生宏不是一个好主意,在这里我不同意Paul Graham的观点。这并不是因为有时你想变得肮脏(不卫生),而是因为卫生宏最终会变得复杂或复杂。彼得·塞贝尔(Peter Seibel)的实用公共Lisp对宏有很好的介绍。保罗·格雷厄姆(Paul Graham)的《Lisp论》(On Lisp)可能是更复杂例子的一个很好来源。另外,请看一下Common Lisp中的内置宏。我只使用Scheme宏(
定义语法
)来处理一些小问题,例如更好的lambda语法:
(define-syntax [: x]
(syntax-case x ()
([src-: e es ...]
(syntax-case (datum->syntax-object #'src-: '_) ()
(_ #'(lambda (_) (e es ...)))))))
它让你写作
[: / _ 2] ; <-- much better than (lambda (x) (/ x 2))
define syntax
很奇怪,因为它只适用于非常简单的宏,您很高兴无法捕获变量;还有非常复杂的宏DSL,您很高兴无法轻松捕获变量。在第一种情况下,您希望编写代码而不去考虑它,而在第二种情况下,您已经对DSL考虑得够多了,因此您愿意使用语法规则
/语法案例
语言编写部分代码,该语言不是Scheme,以避免使bug神秘化
但我在Scheme中不太使用宏。惯用方案的功能非常强大,很多时候,您只想编写一个功能性程序,然后隐藏一些lambda。我上了函数火车,现在相信如果你有一个懒惰的语言或lambda的好语法,即使这是没有必要的,所以宏在纯函数风格中也不是那么有用
因此,我推荐并推荐。如果您想使用PLT方案,我认为他们的大多数
defmacro
宏将与define macro
一起使用。或者只使用Common Lisp。一个更高级的宏(不是lambda形式的伪装)的例子是Common Lisp的宏,带有插槽,这使对象插槽访问看起来像普通变量访问:
(with-slots (state door) car
(when (eq state :stopped)
(setq state :driving-around)
(setq door :closed)))
请注意,这与将插槽值绑定到本地变量并访问这些变量不同,因为使用插槽可以通过SETQ更改插槽,并立即查看外部更改。需要宏来实现新的控制结构和新的绑定构造 因此,请在下面的位置查找这些类型的构造。 在PLaneT,您可以浏览文档和代码 新控制结构的示例: 要查找新绑定表单的示例,请查找以“with-”开头的宏。 另一个有用的例子是来自PLaneT的math.plt
; Within a (with-modulus n form1 ...) the return values of
; the arithmetival operations +, -, * and ^ are automatically
; reduced modulo n. Furthermore (mod x)=(modulo x n) and
; (inv x)=(inverse x n).
; Example: (with-modulus 3 (^ 2 4)) ==> 1
(define-syntax (with-modulus stx)
(syntax-case stx ()
[(with-modulus e form ...)
(with-syntax ([+ (datum->syntax-object (syntax with-modulus) '+)]
[- (datum->syntax-object (syntax with-modulus) '-)]
[* (datum->syntax-object (syntax with-modulus) '*)]
[^ (datum->syntax-object (syntax with-modulus) '^)]
[mod (datum->syntax-object (syntax with-modulus) 'mod)]
[inv (datum->syntax-object (syntax with-modulus) 'inv)])
(syntax (let* ([n e]
[mod (lambda (x) (modulo x n))]
[inv (lambda (x) (inverse x n))]
[+ (compose mod +)]
[- (compose mod -)]
[* (compose mod *)]
[square (lambda (x) (* x x))]
[^ (rec ^ (lambda (a b)
(cond
[(= b 0) 1]
[(even? b) (square (^ a (/ b 2)))]
[else (* a (^ a (sub1 b)))])))])
form ...)))]))
本文提出了一种用宏实现有限状态机的函数式编程方法
本书以一个完整的基于宏的miniKanren实现作为结尾,miniKanren是本书中使用的逻辑编程语言。与本书相比,本书更正式、更简洁地介绍了miniKanren及其实现。当程序不满足要求时,我会使用它们 当我过去在掌上做很多计划时,我有一个
curry
宏。它非常方便。Scheme宏允许您添加原始语言作者自己没有包含的功能;这就是宏背后的全部哲学
这里有一个小例子:PLT方案提供了一种称为幻灯片的语言来编写演示文稿。我使用宏将幻灯片编号与幻灯片关联,以便更轻松地管理它们。我编写了一个提供中缀语法的宏。不要太花哨;没有优先权。虽然我通常对前缀语法很在行,但我更喜欢
aif
的定义(和卫生性!):`(定义语法参数it#f)(定义语法aif(语法解析器[(u-test-then-else)#’(let([result test])(语法参数化([it(make-rename-transformer-result)](If-result-then-else))))
; Within a (with-modulus n form1 ...) the return values of
; the arithmetival operations +, -, * and ^ are automatically
; reduced modulo n. Furthermore (mod x)=(modulo x n) and
; (inv x)=(inverse x n).
; Example: (with-modulus 3 (^ 2 4)) ==> 1
(define-syntax (with-modulus stx)
(syntax-case stx ()
[(with-modulus e form ...)
(with-syntax ([+ (datum->syntax-object (syntax with-modulus) '+)]
[- (datum->syntax-object (syntax with-modulus) '-)]
[* (datum->syntax-object (syntax with-modulus) '*)]
[^ (datum->syntax-object (syntax with-modulus) '^)]
[mod (datum->syntax-object (syntax with-modulus) 'mod)]
[inv (datum->syntax-object (syntax with-modulus) 'inv)])
(syntax (let* ([n e]
[mod (lambda (x) (modulo x n))]
[inv (lambda (x) (inverse x n))]
[+ (compose mod +)]
[- (compose mod -)]
[* (compose mod *)]
[square (lambda (x) (* x x))]
[^ (rec ^ (lambda (a b)
(cond
[(= b 0) 1]
[(even? b) (square (^ a (/ b 2)))]
[else (* a (^ a (sub1 b)))])))])
form ...)))]))