2008-10-29 69 views
9

宏的许多例子似乎都是关于隐藏lambda,例如在CL中打开文件。我正在寻找一些更宏观的宏,特别是在PLT计划中。我想知道何时考虑使用宏与使用函数。你用Scheme Scheme宏做了些什么?

+1

PLT计划现在称为球拍。 见http://www.racket-lang.org/ – Stephen 2010-07-05 15:59:58

回答

5

我只用了很小的事情计划宏(define-syntax),如更好的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)) 

丹·弗里德曼有使用宏OO的一个令人费解的实现:http://www.cs.indiana.edu/~dfried/ooo.pdf

但说实话,我所定义的所有有用的宏d从Paul Graham's On Lisp被盗,通常易于用defmacro(PLT计划中的define-macro)编写。例如,aifdefine-syntax相当丑陋。

(define-syntax (aif x) 
    (syntax-case x() 
    [(src-aif test then else) 
    (syntax-case (datum->syntax-object (syntax src-aif) '_)() 
     [_ (syntax (let ([_ test]) (if (and _ (not (null? _))) then else)))])])) 

define-syntax是,这只是简单的使用非常简单的宏,在那里你很高兴无法捕捉变量的奇数;和非常复杂的宏DSL,你很高兴无法捕捉变量容易。在第一种情况下,您希望编写代码而不考虑它,而在第二种情况下,您已经充分考虑了DSL,您希望将其中的一部分写入syntax-rules/syntax-case语言中,该语言不是Scheme以便避免神秘的错误。


但我没有在Scheme中使用过多的宏。习语方案非常实用,很多时候你只想编写一个功能程序,然后隐藏一些lambda表达式。我开始了功能训练,现在认为如果你对lambda有一个懒惰的语言或者一个好的语法,即使这不是必须的,所以宏在纯粹的功能性风格中并不是那么有用。

所以我建议Practical Common LispOn Lisp。如果你想使用PLT方案,我认为他们的defmacro宏中的大部分都可以与define-macro一起使用。或者只是使用Common Lisp。

+1

如果使用语法参数,`aif`变得更清晰(定义hygenic!):`(define-syntax-parameter it #f)(define-syntax aif语法分析器[(_ test then else)#'(let([result test])(syntax-parameterize([it(make-rename-transformer result)])(if result then else)))])) – Jack 2014-10-07 19:22:37

7

我会开始回答最后一个问题。何时使用宏而不是函数。宏做功能不能做的事情,功能做宏不能做的事情,所以很难混合它们,但是让我们深入一下。

当您希望参数评估时使用函数,而当您希望参数未评估时使用宏。这不是很有用,是吗?当你想以不同的方式写东西时,当你看到一个模式并且你想要抽象时,你使用宏。例如:我定义了三个称为foo-create,foo-process和foo-destroy的函数,用于foo的不同值以及类似的机构,其中唯一的变化是foo。有一个模式,但是对于一个函数来说是一个太高的级别,所以你创建一个宏。

以我卑微的经验,Scheme中的宏和其他Lisp一样多,像Common Lisp或Clojure。我认为这证明卫生宏可能不是一个好主意,在这里我不同意Paul Graham的看法。这不是因为有时候你想要变得肮脏(不卫生),而是因为卫生的宏变得复杂或错综复杂。

+0

“因为卫生的宏观变得复杂或错综复杂” - 我不认为这是因为卫生本身;这很可能是因为Scheme卫生宏是“高级”,必须用除Scheme之外的语言编写(就我而言,这比计划本身更不方便) 这就是为什么我喜欢Common Lisp和在Scheme中仍然使用define-macro,尽管R5RS具有这种夸张的语法规则的东西......:-) – Jay 2010-06-27 23:38:51

3

Peter Seibel编写的Practical Common Lisp对宏有很好的介绍。关于Lisp,Paul Graham,可能是更复杂的例子的一个很好的来源。另外,请查看Common Lisp中的内置宏。

+1

Scheme宏!=常用Lisp宏 – 2008-10-29 18:41:29

1

一种更先进的宏的示例不是伪装的λ形式是常见Lisp的宏与时隙,这使得对象插槽存取样子普通可变访问:

(with-slots (state door) car 
    (when (eq state :stopped) 
    (setq state :driving-around) 
    (setq door :closed))) 

注意,这与将插槽值绑定到局部变量并访问它们不同,因为带插槽允许您通过SETQ更改插槽并立即查看外部更改。

+0

setq的使用确实被弃用,以支持setf。如果像这样的例子使用setf,那么对于新的(通用)lispers来说就不那么容易混淆了。 – simon 2008-10-29 22:06:43

8

宏需要为了实现新的控制结构和新的绑定结构。

因此在http://planet.plt-scheme.org寻找这些种类的构造。 在PLaneT上你都浏览文档和代码。新的控制结构

例子:

http://planet.plt-scheme.org/package-source/soegaard/control.plt/2/0/planet-docs/manual/index.html

要找到新的结合形式的例子,查找以“与 - ”开头的宏。 另一个有用的例子是在math.plt中也从PLaneT中找到的。

; 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 ...)))])) 
3

Automata via Macros本文提供了一个函数编程的珍珠,通过Scheme中的宏实现有限状态机。

该书The Reasoned Schemer以本书中使用的逻辑编程语言miniKanren的完全基于宏的实现结束。 This paper介绍miniKanren及其实施比本书更正式和简洁。

+0

通过宏链接自动机是纯金。我有一个巨大的哈哈!时刻阅读它。从我+1。 – 2011-07-19 04:47:04

0

我在程序不足时使用它们。

1

我有一个curry宏,当我用我的手掌做了很多计划。这非常方便。

1

Scheme宏允许您添加原始语言作者未包含的特征;这是宏观背后的全部理念。

这是一个小例子:PLT Scheme提供了一种用于编写幻灯片演示的语言。我使用宏将幻灯片编号与幻灯片相关联,以便我可以更轻松地管理它们。

1

我写了一个提供中缀语法的宏。没什么太花哨的;没有优先权。虽然我通常使用前缀语法,但我更喜欢<和>的中缀。