国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Lisp已死,Lisp萬歲!

開發 后端 開發工具
有一句古話,叫做“國王已死,國王萬歲!”它的意思是,老國王已經死去,國王的兒子現在繼位。這句話的幽默,就在于這兩個“國王”其實指的不是同一個人,而你咋一看還以為它自相矛盾。今天我的話題仿效了這句話,叫做“Lisp 已死,Lisp 萬歲!”希望到最后你會明白這是什么意思。

有一句古話,叫做“國王已死,國王萬歲!”它的意思是,老國王已經死去,國王的兒子現在繼位。這句話的幽默,就在于這兩個“國王”其實指的不是同一個人,而你咋一看還以為它自相矛盾。今天我的話題仿效了這句話,叫做“Lisp 已死,Lisp 萬歲!”希望到***你會明白這是什么意思。

首先,我想總結一下 Lisp 的優點。你也許已經知道,Lisp 身上最重要的一些優點,其實已經“遺傳”到了幾乎每種流行的語言身上(Java,C#,JavaScript,Python, Ruby,Haskell,……)。由于我已經在其他博文里詳細的敘述過其中一些,所以現在只把這些 Lisp 的優點簡單列出來(關鍵部分加了鏈接):

  • Lisp 的語法是世界上最精煉,最美觀,也是語法分析起來***效的語法。這是 Lisp ***的,其他語言都沒有的優點。有些人喜歡設計看起來很炫的語法,其實都是自找麻煩。為什么這么說呢,請參考這篇《談語法》。

  • Lisp 是***個可以在程序的任何位置定義函數,并且可以把函數作為值傳遞的語言。這樣的設計使得它的表達能力非常強大。這種理念被 Python,JavaScript,Ruby 等語言所借鑒。

  • Lisp 有世界上***大的宏系統(macro system)。這種宏系統的表達力幾乎達到了理論所允許的極限。如果你只見過 C 語言的“宏”,那我可以告訴你它是完全沒法跟 Lisp 的宏系統相提并論的。

  • Lisp 是世界上***個使用垃圾回收(garbage collection)的語言。這種超前的理念,后來被 Java,C# 等語言借鑒。

想不到吧,現代語言的很多優點,其實都是來自于 Lisp — 世界上第二古老的程序語言。所以有人才會說,每一種現代語言都在朝著 Lisp 的方向“進化”。如果你相信了這話,也許就會疑惑,為什么 Lisp 今天沒有成為主流,為什么 Lisp Machine 會被 Unix 打敗。其實除了商業原因之外,還有技術上的問題

早期的 Lisp 其實普遍存在一個非常嚴重的問題:它使用 dynamic scoping。所謂 dynamic scoping 就是說,如果你的函數定義里面有“自由變量”,那么這個自由變量的值,會隨著函數的“調用位置”的不同而發生變化。

比如下面我定義一個函數 f,它接受一個參數 y,然后返回 x 和 y 的積。

  1. (setq f   
  2.       (let ((x 1))   
  3.         (lambda (y) (* x y)))) 

這里 x 對于函數 (lambda (y) (* x y)) 來說是個“自由變量”(free variable),因為它不是它的參數

看著這段代碼,你會很自然的認為,因為 x 的值是 1,那么 f 被調用的時候,結果應該等于 (* 1 y),也就是說應該等于 y 的值。可是這在 dynamic scoping 的語言里結果如何呢?我們來看看吧。

(你可以在 emacs 里面試驗以下的結果,因為 Emacs Lisp 使用的就是 dynamic scoping。)

如果我們在函數調用的外層定義一個 x,值為 2:

  1. (let ((x 2))  
  2.   (funcall f 2)) 

因為這個 x 跟 f 定義處的 x 的作用域不同,所以它們不應該互相干擾。所以我們應該得到 2。可是,這段代碼返回的結果卻為 4。

再來。我們另外定義一個 x,值為 3:

  1. (let ((x 3))  
  2.   (funcall f 2)) 

我們的期望值還是 2,可是結果卻是 6。

再來。如果我們直接調用:

  1. (funcall f 2) 

你想這次總該得到 2 了吧?結果,出錯了:

  1. Debugger entered--Lisp error: (void-variable x)  
  2.   (* x y)  
  3.   (lambda (y) (* x y))(2)  
  4.   funcall((lambda (y) (* x y)) 2)  
  5.   eval_r((funcall f 2) nil)  
  6.   eval-last-sexp-1(nil)  
  7.   eval-last-sexp(nil)  
  8.   call-interactively(eval-last-sexp nil nil) 

看到問題了嗎?f 的行為,隨著調用位置的一個“名叫 x”的變量的值而發生變化。而這個 x,跟 f 定義處的 x 其實根本就不是同一個變量,它們只不過名字相同而已。這會導致非常難以發現的錯誤,也就是早期的 Lisp 最令人頭痛的地方。我的老師 Dan Friedman 當年就為此痛苦了很多年,直到 Scheme 的出現,他才歡呼道:“終于有人把它給做對了!”

(附帶說一句,Scheme 不是 Dan Friedman 發明的,而是 Guy Steele 和 Gerald Sussman。然而,Friedman 對程序語言的本質理解,其實超越了 Lisp 的范疇,并且對 Scheme 的后期設計做出了重要的貢獻。以至于 Sussman 在 Friedman 的 60 大壽時發表演說,戲稱自己比起 Friedman 來,“只是 Scheme 的用戶”。)

好在現在的大部分語言其實已經吸取了這個教訓,所以你不再會遇到這種讓人發瘋的痛苦。不管是 Scheme, Common Lisp, Haskell, OCaml, Python, JavaScript…… 都不使用 dynamic scoping。

那現在也許你了解了,什么是讓人深惡痛絕的 dynamic scoping。如果我告訴你,Lisp Machine 所使用的語言 ZetaLisp(也叫 Lisp Machine Lisp)使用的也是 dynamic scoping,你也許就明白了為什么 Lisp Machine 會失敗。因為它跟現在的 Common Lisp 和 Scheme,真的是天壤之別。我寧愿寫 C++,Java 或者 Python,也不愿意寫 ZetaLisp 或者 Emacs Lisp。

話說回來,為什么早期的 Lisp 會使用 dynamic scoping 呢?其實這根本就不是一個有意的“設計”,而是一個無意的“巧合”。你幾乎什么都不用做,它就成那個樣子了。這不是開玩笑,如果你在 emacs 里面顯示 f 的值,它會打印出:

  1. '(lambda (y) (* x y)) 

這說明 f 的值其實是一個 S 表達式,而不是像 Scheme 一樣的“閉包”(closure)。原來,Emacs Lisp 直接把函數定義處的 S 表達式 ‘(lambda (y) (* x y)) 作為了函數的“值”,這是一種很幼稚的做法。如果你是***次實現函數式語言的新手,很有可能就會這樣做。Lisp 的設計者當年也是這樣的情況。

簡單倒是簡單,麻煩事接著就來了。調用 f 的時候,比如 (funcall f 2),y 的值當然來自參數 2,可是 x 的值是多少呢?答案是:不知道!不知道怎么辦?到“外層環境”去找唄,看到哪個就用哪個,看不到就報錯。所以你就看到了之前出現的現象,函數的行為隨著一個完全無關的變量而變化。如果你單獨調用 (funcall f 2) 就會因為找不到 x 的值而出錯。

那么正確的實現函數的做法是什么呢?是制造“閉包”(closure)。這也就是 Scheme,Common Lisp 以及 Python,C# 的做法。在函數定義被解釋或者編譯的時候,當時的自由變量(比如 x)的值,會跟函數的代碼綁在一起,被放進一種叫做“閉包”的結構里。比如上面的函數,就可以表示成這個樣子:(Closure '(lambda (y) (* x y)) '((x . 1)))。

在這里我用 (Closure ...) 表示一個“結構”(就像 C 語言的 struct)。它的***個部分,是這個函數的定義。第二個部分是 '((x . 1)),它是一個“環境”,其實就是一個從變量到值的映射(map)。利用這個映射,我們記住函數定義處的那個 x 的值,而不是在調用的時候才去瞎找。

我不想在這里深入細節。如果你對實現語言感興趣的話,可以參考我的另一篇博文《怎樣寫一個解釋器》。它教你如何實現一個正確的,沒有以上毛病的解釋器。

與 dynamic scoping 相對的就是“lexical scoping”。我剛才告訴你的閉包,就是 lexical scoping 的實現方法。***個實現 lexical scoping 的語言,其實不是 Lisp 家族的,而是 Algol 60。“Algol”之所以叫這名字,是因為它的設計初衷是用來實現算法(algorithm)。其實 Algol 比起 Lisp 有很多不足,但在 lexical scoping 這一點上它卻做對了。Scheme 從 Algol 60 身上學到了 lexical scoping,成為了***個使用 lexical scoping 的“Lisp 方言”。9 年之后,Lisp 家族的“集大成者” Common Lisp 誕生了,它也采用了 lexical scoping。看來英雄所見略同。

你也許發現了,Lisp 其實不是一種語言,而是很多種語言。這些被人叫做“Lisp 家族”的語言,其實共同點只是它們的“語法”:它們都是基于 S 表達式。如果你因此對它們同樣贊美的話,那么你贊美的其實只是 S 表達式,而不是這些語言本身。因為一個語言的本質應該是由它的語義決定的,而跟語法沒有很大關系。你甚至可以給同一種語言設計多種不同的語法,而不改變這語言的本質。比如,我曾經給 TeX 設計了 Lisp 的語法,我把它叫做 SchTeX(Scheme + TeX)。SchTeX 的文件看起來是這個樣子:

  1. (documentclass article (11pt))  
  2.  
  3. (document  
  4.  
  5.   (abstract (...))  
  6.  
  7.   (section (First Section)  
  8.  
  9.       ... )  
  10.  
  11.   (section (Second Section)  
  12.  
  13.       ... )  
  14.  

很明顯,雖然這看起來像是 Scheme,本質卻仍然是 TeX。

所以,因為 Scheme 的語法使用 S 表達式,就把 Scheme 叫做 Lisp 的“方言”,其實是不大準確的做法。Scheme 和 Emacs Lisp,Common Lisp 其實是三種不同的語言。Racket 曾經叫做 PLT Scheme,但是它跟 Scheme 的區別日益增加,以至于現在 PLT 把它改名叫 Racket。這是有他們的道理的。

所以,你也許明白了為什么這篇文章的標題叫做“Lisp 已死,Lisp 萬歲!” 因為這句話里面的兩個 “Lisp”其實是完全不同的語言。“Lisp 已死”,其實是說 ZetaLisp 這樣的 Lisp,由于嚴重的設計問題,已經死去。而“Lisp 萬歲”,是說像 Scheme,Common Lisp 這樣的 Lisp,還會繼續存在。它們先進于其它語言的地方,也會更多的被借鑒,被發揚廣大。

(其實老 Lisp 的死去還有另外一個重要的原因,那就是因為早期的 Lisp 編譯器生成的代碼效率非常低下。這個問題我留到下一篇博文再講。)

原文鏈接:http://blog.sina.com.cn/s/blog_5d90e82f0101jo6r.html

責任編輯:林師授 來源: 王垠的博客
相關推薦

2013-02-26 11:01:42

CIO信息化大數據云計算

2010-04-06 09:02:59

Solaris甲骨文Sun

2015-04-23 09:34:18

CoffeeScripJavaScript開

2024-10-15 11:16:18

2019-10-11 08:58:21

Hadoop開源

2024-12-10 09:07:17

2015-11-05 10:17:42

網絡工程師IT人員

2018-01-08 07:58:51

深度學習編程人工智能

2025-01-13 08:20:00

AI模型訓練

2012-06-04 10:34:17

Lisp

2009-09-03 18:32:43

Lisp函數

2017-03-16 09:30:56

LispAI數據結構

2017-01-05 13:31:33

Lisp加法運算

2012-11-22 10:11:16

LispLisp教程

2011-04-15 09:23:33

IETFLISP路由器

2014-12-24 13:53:48

2011-10-14 09:20:48

Lisp

2010-10-15 10:35:18

2013-03-18 09:30:18

Lisp

2015-05-20 09:05:40

點贊
收藏

51CTO技術棧公眾號

国产精品久久久久久久免费大片| 久久久久久9999| 国精产品一区一区三区mba视频| 亚洲国产日产av| 色一情一乱一伦一区二区三区| 亚洲人成精品久久久| 精品国产依人香蕉在线精品| 亚洲最大黄色| 日本 国产 欧美色综合| 国产一区深夜福利| 欧美在线电影| 久久全国免费视频| 欧美电影免费观看| 久久精品亚洲精品国产欧美kt∨| 亚洲狼人综合干| 免费成人你懂的| 亚洲一区二区精品在线观看| 国产人成精品一区二区三| 欧美一级片在线播放| 99精品国产在热久久婷婷| 国产精品久久久久久超碰| 欧美国产日韩电影| 成人黄色综合网站| 91精品黄色| 国内精品久久久久久久影视简单| 制服丝袜一区二区三区| 成人欧美亚洲| 欧美在线激情| 一区二区日本视频| 人人干人人视频| 91年精品国产| 国产av熟女一区二区三区| 经典一区二区三区| 国产91在线视频观看| 亚洲在线中文字幕| 91高清视频在线观看| 欧美精品第一页在线播放| 亚洲精品孕妇| 日本成年人网址| 欧洲亚洲精品在线| 伊人永久在线| 91网址在线看| 欧美xxxx黑人又粗又长密月| 另类专区欧美蜜桃臀第一页| 正在播放一区二区三区| 久久色视频免费观看| 国产视频网站在线| 亚洲精品日韩欧美| 国产高清亚洲| 亚洲一区二区三区xxx视频| 老司机午夜免费精品视频| 独立日3在线观看完整版| 91精品国产aⅴ一区二区| 国产精品白丝久久av网站| 欧美激情一级精品国产| 国产99精品国产| 奇米影视888狠狠狠777不卡| 91av福利视频| 一本一道久久综合狠狠老精东影业| 欧美一区二区三区视频免费 | av资源在线| 视频在线精品一区| 亚洲国产中文字幕在线观看| 久久一二三区| 中文在线а√在线8| 国产日韩一区二区在线| 97国产精品人人爽人人做| 亚洲一区二区视频在线| 外国成人免费视频| 2024最新电影在线免费观看| 无码免费一区二区三区免费播放| 97精品欧美一区二区三区| 亚洲卡通欧美制服中文| 超碰成人在线观看| 精品久久一区二区三区蜜桃| 中文一区一区三区高中清不卡| 欧美xxxx做受欧美88bbw| 色悠悠久久久久| 三上悠亚亚洲一区| 一区二区三区一级片| 日韩美女精品在线| 亚洲区综合中文字幕日日| 亚洲国产99精品国自产| 黄色av免费在线观看| 欧洲亚洲一区二区| 色诱女教师一区二区三区| 国产超碰在线一区| 国产精品久久麻豆| 午夜精品久久久久久99热| 成人午夜私人影院| 日韩大片b站免费观看直播| 欧美日韩三级一区二区| 久久免费影院| 亚洲xxxx视频| 欧美精品日韩精品| 欧美三级在线播放| 成人免费视频caoporn| 欧美猛男做受videos| 久草香蕉在线| 高清国产在线一区| 4438x成人网最大色成网站| 日韩成人一级大片| 妖精视频一区二区三区| 毛片在线视频| 天天干夜夜干| 中文字幕乱码人妻综合二区三区 | 欧美福利视频在线| 国产精品色哟哟| 色88久久久久高潮综合影院| www视频在线免费观看| 免费一级特黄特色毛片久久看| 欧美a级黄色大片| 亚洲高清视频在线| 久久人人爽人人爽人人片av不| 很污的网站在线观看| 91精品导航| 欧美国产欧美亚洲国产日韩mv天天看完整| 毛片av一区二区三区| 日本中文字幕中出在线| 裸模一区二区三区免费| 在线不卡中文字幕| 国产亚洲激情| av在线网址观看| 欧美日韩精品免费观看视一区二区 | 欧美在线亚洲综合一区| 天天夜夜亚洲| 国产狼人综合免费视频| 亚洲国产精品自拍| 中文字幕亚洲精品乱码| 成人在线免费观看| 久久大香伊蕉在人线观看热2| 欧美日韩精品免费| 免费看欧美美女黄的网站| 日本不卡免费高清视频在线| 成年人视频大全| 九九九久久久久久| 亚洲人成电影网站色mp4| 欧美日韩中文一区二区| 欧美色图另类| 精选一区二区三区四区五区| 精品国产免费视频| 国产69精品久久99不卡| 成人性生交大片免费看96| 成人h动漫在线| 91免费福利视频| 91精品欧美一区二区三区综合在| 日本欧美大码aⅴ在线播放| 亚洲天堂一区二区| 成人精品小视频| 国产精品女主播视频| 欧美亚洲一区二区在线| 男人的天堂久久精品| 国产一区一区| 亚洲激情图片小说视频| av伊人久久| 青草在线视频| 男女激情无遮挡| 国产成人精品一区二区三区| 欧美性猛交xxxx黑人猛交| 麻豆精品一区二区三区| 99re91这里只有精品| 欧美日本韩国一区二区| 中日韩在线视频| 欧美激情在线一区| 欧美色图在线观看| 不卡av免费在线观看| 91综合网人人| 最新欧美色图| 日本亚洲天堂| 亚洲一区二区三区乱码| 777精品视频| 日韩视频免费观看高清在线视频| 99久久精品国产一区| 在线观看日韩| www.久久| 国产三级在线观看| 可以看毛片的网址| 国产在线高清精品| 亚洲欧美国产高清va在线播| 亚洲一卡二卡三卡四卡五卡| 国产精品主播| 欧美绝顶高潮抽搐喷水合集| 三区四区电影在线观看| 午夜肉伦伦影院| 精品国产乱码久久久久软件 | 国产视频一区二区在线观看| 午夜日韩电影| 成人毛片免费| 成全电影播放在线观看国语| www国产黄色| 精品伦理一区二区三区| 91精品国产精品| 国产午夜精品麻豆| 在线观看一区二区视频| 久久久亚洲精品一区二区三区| 国产精品制服诱惑| 亚洲精选中文字幕| 色综合久久综合中文综合网| 久久久不卡网国产精品二区| 日本vs亚洲vs韩国一区三区二区|