2017-01-10 39 views
0
  1. 關於衛生宏觀兩個關於球拍宏觀

    的問題,我並不完全瞭解衛生宏觀調控工作。這裏有兩個例子。
    第一個是:


    #lang racket 
    (define-syntax (g stx) 
     (syntax-case stx() 
     ([_ arg] 
     #'(display arg)))) 

    (let ([display 1]) 
     (g 3)) 

這工作得很好,但是這一個:


    #lang racket 
    (define-syntax (g stx) 
     (syntax-case stx() 
     ([_ arg] 
     #'(display arg)))) 

    (define display 1) 

    (g 3) 

將引發異常。如何解釋這兩種情況的區別?

  • 如何定義這樣

    我希望定義一個宏,以允許在球拍匿名遞歸函數的宏。 這一次不會起作用,因爲易復發不模塊中定義的:

  • 
        #lang racket 
        (define Z 
         (λ(recur) 
         ((λ(x) (recur (λ(y) (x x) y))) 
         (λ(x) (recur (λ(y) (x x) y)))))) 
    
        (define-syntax-rule (R proc) 
         (Z (λ(recur) proc))) 
    
        ((R (λ(n) 
          (if [= n 1] 
           1 
           (* n (recur (- n 1)))))) 3) 
    

    如何實現這一目標?

    +0

    這個問題會更好,如果它被分成了兩個不同的問題,每個問題都是獨立的。 – chwarr

    回答

    1

    所以你想打破hygene?你需要得到recur有原始表單的詞彙上下文使得recur將被視爲相同的標識符。你可以用datum->syntax做到這一點,結果可能是這個樣子:

    (define-syntax (recur-λ stx) 
        (syntax-case stx() 
        [(_ args body ...) 
        (with-syntax ([recur-stx (datum->syntax stx 'recur)]) 
         #'(Z (λ (recur-stx) 
           (λ args body ...))))])) 
    

    現在只要你ARGS或體嵌套介紹recur它會工作:

    ; multiple argument recursion 
    (define Z 
        (λ (f) 
        ((λ (g) (g g)) 
        (λ (g) 
         (f (λ args (apply (g g) args))))))) 
    
    
    ; ackerman  
    ((recur-λ (m n) 
        (cond 
         ((= m 0) (+ n 1)) 
         ((= n 0) (recur (- m 1) 1)) 
         (else (recur (- m 1) (recur m (- n 1)))))) 
    3 
    6) 
    ; ==> 509 
    

    它贏得了

    ((recur-λ (recur) (recur 1)) 1) 
    ; ==> error: recur not a procedure 
    

    當然,如果你M:「如果你讓recur參數科技工作AKE一個嵌套的綁定:

    ((recur-λ (a) 
        (define recur a) 
        (recur 1)) 
    1) 
    ; ==> error: recur not a procedure 
    

    當然,您可以通過macroexpander一步,它會告訴你,它是這樣的:

    (expand-once 
    #'(recur-λ (m n) 
        (cond 
         ((= m 0) (+ n 1)) 
         ((= n 0) (recur (- m 1) 1)) 
         (else (recur (- m 1) (recur m (- n 1))))))) 
    
    ; ==> 
    ; #'(Z 
    ; (λ (recur) 
    ;  (λ (m n) 
    ;  (cond 
    ;   ((= m 0) (+ n 1)) 
    ;   ((= n 0) (recur (- m 1) 1)) 
    ;   (else (recur (- m 1) (recur m (- n 1)))))))) 
    
    +0

    正是我想要的,謝謝!對我來說,瞭解宏有很多... – Eleven

    3

    要回答你的第一個問題,你在這裏忘記的是,當你做一個模塊級別define那樣的時候,這個定義是綁定到整個模塊的。所以,你可以,理論上寫第二代碼塊這樣的:

    #lang racket 
    (let ([display 1]) 
        (define-syntax (g stx) 
        (syntax-case stx() 
         ([_ arg] 
         #'(display arg)))) 
    
        (g 3)) 
    

    而現在它是有道理的,爲什麼你會得到一個錯誤,因爲在您的宏顯示器勢必1,這是不是一個函數。

    長話短說,想衛生就像詞彙的範圍。無論display是什麼,當你的定義你的宏是它將是。 (這是相對於其他語言的宏,在任何display勢必會當你電話(或真擴大)宏,是它會是什麼。

    現在,爲了回答你的第二個問題,我道歉,但我不清楚你在這裏要問什麼,如果你可以清理一下,那麼我可以填寫這部分的答案

    +0

    感謝您的回答,它幫助了很多。正如Sylwester所說,我真正想做的是在第二個問題中打破hygene。 – Eleven