[Macros] LISP宏可以走多遠?


Answers

是的,您可以重新定義語法,以便Lisp成為編譯器。 你使用“Reader宏”來做到這一點,它與你可能想到的普通的“Compiler宏”不同。

Common Lisp擁有內置的工具來為讀者和讀者宏定義新的語法來處理這個語法。 這個處理是在讀取時完成的(在編譯或者eval時間之前)。 要了解更多有關在Common Lisp中定義閱讀器宏的信息,請參閱Common Lisp Hyperspec - 您將需要閱讀Ch。 2,“語法”Ch。 23,“讀者” (我相信Scheme有相同的功能,但我不太熟悉它 - 請參閱Arc編程語言Scheme源文件 )。

作為一個簡單的例子,假設您希望Lisp使用大括號而不是括號。 這需要像下面的讀者定義:

;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
  (declare (ignore inchar))
  (read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)

(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )

;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )

你告訴Lisp,{就像一個(而且那個)就像一個)。 然後你創建一個函數( lcurly-brace-reader ),當讀者看到一個{,並且你使用set-macro-character把這個函數賦值給{ 然後你告訴Lisp(和)就像[和](也就是說,沒有意義的語法)。

你可以做的其他事情包括,例如, 創建一個新的字符串語法,或者使用[和]來包含內附符號表示法,並將其處理成S表達式。

你也可以遠遠超出這個範圍,用你自己的宏觀角色重新定義整個語法,這將觸發讀者的行為,所以天空真的是極限。 這只是Paul Graham其他人一直說Lisp是編寫編譯器的好語言的原因之一。

Question

我已經讀了很多,LISP可以重新定義語法,大概是用宏。 我很好奇這實際上走了多遠? 你能否重新定義語言結構,使其成為另一種語言的編譯器? 例如,你能否將LISP的功能性改變成更面向對象的語法和語義,也許有更接近Ruby的語法?

特別是,有可能使用宏擺脫括號的地獄? 我已經學會了足夠多的(Emacs-)LISP來自定義Emacs的微特性,但是我非常好奇宏可以在定制語言的時候走多遠。




括號地獄? 在我看到沒有更多的括號:

(function toto)

比在:

function(toto);

而且,

(if tata (toto)
  (titi)
  (tutu))

不超過:

if (tata)
  toto();
else
{
  titi();
  tutu();
}

我看到更少的括號和“;” 雖然。




常規宏對對象列表進行操作。 通常,這些對像是其他列表(因此形成樹)和符號,但它們可以是其他對象,如字符串,哈希表,用戶定義的對像等。這些結構被稱為s-exps

所以,當你加載一個源文件時,你的Lisp編譯器將解析文本並產生s-exps。 宏對這些進行操作。 這很好用,這是在s-exps的精神範圍內擴展語言的一個奇妙的方法。

另外,前面提到的解析過程可以通過“讀取器宏”進行擴展,使您可以自定義編譯器將文本轉換為s-exps的方式。 然而,我建議你接受Lisp的語法,而不是將其彎曲到別的東西上。

當你提到Lisp的“功能性”和Ruby的“面向對象的語法”時,你聽起來有些困惑。 我不確定應該使用什麼“面向對象的語法”,但是Lisp是一種多範式的語言,它非常好地支持面向對象的編程。

順便說一下,當我說Lisp時,我的意思是Common Lisp

我建議你放棄你的偏見,並給Lisp一個誠實的去




Lisp的新手想要“擺脫所有的括號”。 它持續幾個星期。 在通常的S表達式解析器之上,沒有任何項目能夠建立一個嚴肅的通用編程語法,因為程序員不可避免地喜歡你目前認為的“括號地獄”。 這需要一點習慣,但不是太多! 一旦你習慣了,並且你可以真正感受到默認語法的可塑性,回到那些只有一種方式來表達任何特定的編程結構的語言是真正的光柵。

這就是說,Lisp是構建域特定語言的一個很好的基礎。 和XML一樣好,甚至更好。

祝你好運!




請參閱這個例子,了解如何使用XML模板這樣的複雜任務來擴展lisp閱讀器。

http://common-lisp.net/project/cl-quasi-quote/present-class.html

用戶庫在編譯時將XML的靜態部分編譯為UTF-8編碼的文字字節數組,以準備將其寫入網絡流中。 並且它們在正常的lisp宏中可用,它們是正交的...逗號字符的放置影響哪些部分是恆定的,哪些應該在運行時進行評估。

更多詳情請訪問: http : //common-lisp.net/project/cl-quasi-quote/

Common Lisp語法擴展的另一個項目: http : //common-lisp.net/project/cl-syntax-sugar/




如果你想Lisp看起來像Ruby使用Ruby。

可以像使用Ruby(和Python)一樣以非常簡單的方式使用Ruby,這是他們如此迅速獲得接受的主要原因之一。




其中一個引起我頭腦的宏的用法是對DB的SQL請求進行編譯時驗證。

一旦意識到自己在編譯時已經掌握了全部的語言,就會開啟有趣的新視角。 這也意味著你可以用有趣的新方式(如渲染編譯不可複制,可以很容易地變成調試噩夢)在自己的腳下進行拍攝。