2012-02-22 99 views

回答

18

條款不是完全相同的,但它們不是唯一的或者(這個回答假設方案):

  • 一個特殊形式(也稱爲語法該計劃的報告)是不根據函數應用程序的默認規則評估的表達式。 (默認的規則,只是明確的,是eval所有的子表達式,然後apply第一個到其他結果列表的結果。)
  • 宏系統是一個語言特性這允許在語言本身內定義新的特殊形式。 A 是使用宏系統定義的特殊形式。

所以,你可以說,「特殊形式」是屬於接口語義的術語,而「宏」是屬於實施的術語。 「特殊形式」意思是「這些表達式用特殊規則來評估」,而「宏」則意味着「這裏是評估某些表達式的特殊規則的實現。「

現在一個重要的事情是,大多數方案的特殊形式可以從原語的一個非常小的核心被定義爲宏:lambdaif和宏的最小方案的實現,只提供了這些仍然可以實現,其餘爲宏。最近的計劃報告通過引用諸如可以用宏定義的「庫語法」這樣的特殊形式來進行區分,但是實際上,實際的計劃系統通常實現一組更豐富的形式作爲原語。對於表達而言,唯一重要的是用什麼規則來評估它,而不是這條規則是如何實現的。所以從這個意義上說,一個特殊的表單是否被實現爲一個宏或一個原語。但另一方面,一個Scheme系統的實現細節經常「泄漏」,所以你可能會發現自己正在關注它...

+1

你可以在'lambda'之上實現'if'作爲宏。以及。這不是非常有效,但它是一個很好的知識。 – amalloy 2012-02-23 02:55:34

+0

我覺得這個答案是最清楚的。因爲它根據其語義定義了「特殊形式」 - 也就是說 - 不依賴於實現細節。 – 2012-02-23 15:18:12

+1

@amalloy,我感興趣的是如何做到這一點,你有一個方便的鏈接? – 2013-02-04 13:35:16

4

相較於特殊形式,宏觀形式可以macroexpanded:

CL-USER(1): (macroexpand '(with-slots (x y z) 
           foo 
          (format t "~&X = ~A" x))) 

(LET ((#:G925 FOO)) 
    (DECLARE (IGNORABLE #:G925)) 
    (DECLARE (SB-PCL::%VARIABLE-REBINDING #:G925 FOO)) 
    #:G925 
    (SYMBOL-MACROLET ((X (SLOT-VALUE #:G925 'X)) 
        (Y (SLOT-VALUE #:G925 'Y)) 
        (Z (SLOT-VALUE #:G925 'Z))) 
    (FORMAT T "~&X = ~A" X))) 
T 
+0

嗨馬蒂亞斯。在tAoAI中,Norvig聲稱''setf'是一種特殊的形式。但它做了宏觀展開。例如:'(macroexpand'(setf test 4))'擴展到'(SETQ TEST 4)'也許這本書有錯誤?我在這裏沒有看到'setf':http://www.lispworks.com/documentation/lw60/CLHS/Body/03_ababa.htm#clspecialops – tsikov 2016-07-10 17:15:39

11

Lisp有一定的語言基本,從而彌補了Lisp的形式:

  • 文字數據:數字,字符串,結構...
  • 函數調用,像(sin 2.1)或類似((lambda (a b) (+ a b 2)) 3 4)
  • 特殊運營商用於特殊形式。這些是原始的內置語言元素。請參閱Common Lisp中的Special Operators。這些需要在解釋器和編譯器中實施。 Common Lisp爲開發人員提供了無法引入新的特殊運算符或提供您自己的版本的方法。代碼解析工具需要理解這些特殊的操作符;這些工具通常在Lisp社區中被稱爲「代碼助手」。在Common Lisp標準定義期間,確保數字非常小,並且所有擴展都是通過新函數和新宏完成的。
  • :宏是轉換源代碼的函數。該轉換將遞歸發生,直到源代碼中沒有剩下宏。 Common Lisp具有內置的宏,並允許用戶編寫新的宏。

所以特殊形式和宏之間最重要的實際區別是:特殊的運算符是內置的語法和語義。它們不能由開發人員編寫。宏可以由開發人員編寫。

4

對我來說最實際的區別是在調試器中:宏不顯示在調試器中;相反,宏的擴展中的(通常)不明確的代碼顯示在調試器中。調試這些代碼是一個真正的痛苦,並且在開始依賴這些代碼之前確保您的宏是堅如磐石的一個很好的理由。

+1

如果你沒有一個宏調試器,這是一個問題,但是一些Lisp實際上是這樣做的。例如,Racket有一個甚至可以從[REPL](http://docs.racket-lang.org/xrepl/index.html# \(xrepl._syntax \))中使用。 – 2012-02-24 03:37:23

2

懶惰的

超級簡短的回答,您可以寫自己的macroes任何你想要的時候,雖然你不能添加特殊形式無需重新編譯的Clojure。

相關問題