2008-10-29 126 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

我寫了一個提供中綴語法的宏。沒什麼太花哨的;沒有優先權。雖然我通常使用前綴語法,但我更喜歡<和>的中綴。