目錄
newLISP — 交互式教程
Hello World!
代碼和數據是可以互換的
函數的參數
副作用和 Contexts
表達式序列
可執行文件和動態鏈接(Executables and Dynamic Linking)
在 OSX, Linux 或其他 UNIX 系統:
在 Windows 系統上目標文件需要 .exe 後綴
綁定(Binding)
List 是一種遞歸結構
函數(Functions)
高階函數
lambda 列表
動態范圍(Dynamic Scope)
函數參數列表
宏
Contexts
局部作用域(Lexical Scope)
這份文檔於 2006 年 5 月被 Rick Hanson ([email protected]) 做了一些修正和更新後被轉換成 html 文檔。2008 年 12 月被 L.M 更新到 v.10.0 版本. 版權所有 John W. Small 2004。
你可以到 newLISP 官方網站 www.newLISP.org 下載和安裝這門語言.
關於這個教程的任何意見和問題請發郵件到 [email protected] 。
中文版翻譯時 newLISP 的版本已經到了 10.6 這和當時撰寫文檔的時候,已經相隔甚遠。一些內置函數的名稱發生了變化,語言的功能也擴展了很多。我根據實際的情況修改了相應的章節,這樣所有的代碼就都可以在新的版本上進行測試運行了。
中文翻譯:宋志泉(ssqq) QQ: 104359176 電子郵件:[email protected]
在你的系統上安裝 newLISP 之後, 在 shell 命令行下輸入 newlisp
就可以啟動 REPL (讀取,計算,打印循環).
在 Linux 系統中,你的界面看起來像這樣:
1
$ newlisp
2
> _
如果是在 Windows 平台上,它會是這個樣子:
1
c:\> newlisp
2
> _
在 REPL 啟動後,newLISP 會出現一個響應輸入的提示:
1
> _
在下面的提示中輸入如下表達式,就可以在屏幕上打印出 “Hello World!“.
1
> (println
"Hello World!"
)
newLISP 打印出輸入在 REPL 中提示符後的表達式結果,並等待下一次輸入.
1
> (println
"Hello World!"
)
2
Hello World!
3
"Hello World!"
4
> _
為什麼會打印出兩次呢?
函數 println
的執行結果在屏幕上打印出第一行:
1
Hello World!
函數 println
然後返回字符串 “Hello World!“. 這是它最後一個參數,會返回給 REPL, REPL 會把它顯示在屏幕上,這是第二行的由來。
1
"Hello World!"
REPL 會計算任何表達式,不單單計算函數.
1
>
"Hello World!"
2
"Hello World!"
3
> _
如果你輸入上面的表達式 "Hello World!"
, 它只是返回表達式本身,如果輸入數字結果也是一樣.
1
>
1
2
1
3
> _
現在你可能會想,成對的括號怎麼沒用到呢?如果你以前使用主流的計算機語言,像下面的函數調用看起來是不是更自然一點:
1
println(
"Hello World!"
)
我相信過段時間你會喜歡下面的寫法:
1
(println
"Hello World!"
)
而不是:
1
println(
"Hello World!"
)
因為一些原因,不能詳細解釋,等到你看到更多的關於處理列表和符號的 newLISP代碼後,也許就會明白。
Lisp 的本意是列表處理(List Processor). Lisp 使用 lists 同時表示代碼和數據,它們彼此之間是可以互相轉換的。
以前的 println
表達式是一個真正的擁有兩個元素的列表。
1
(println
"Hello World!"
)
第一個元素是:
1
println
第二個元素是:
1
"Hello World!"
Lisp 總是會將列表作為函數調用進行執行,除非你引用它,從而表明它只是一個字面形式的符號表達式,也就是 – 數據。
1
> '(println
"Hello World!"
)
2
(println
"Hello World!"
)
3
> _
一個符號表達式可以再次被當成代碼運行,比如:
1
> (eval '(println
"Hello World!"
))
2
Hello World!
3
"Hello World!"
4
> _
Lisp 程序可以在運行時構建數據的字面量,然後執行它們!
1
> (eval
'(eval '
(println
"Hello World!"
)))
2
Hello World!
3
"Hello World!"
4
> _
通常單引號 '
是引用 quote
簡寫形式.
1
> (quote (println
"Hello World!"
))
2
(println
"Hello World!"
)
3
> _
你可以想象引用 quote
將它的參數當成字面量返回, 也就是符號化參數.
1
> 'x
2
x
3
> (quote x)
4
' x
5
> '(
1
2
three
"four"
)
6
(
1
2
three
"four"
)
7
> _
符號,例如上面的 x
和 three
, 還有符號列表(symbolic lists)在人工智能領域起著舉足輕重的角色。這個教程不會探討人工智能,但是一旦你學會用 Lisp 編程,你將能明白許多人工智能的教科書的 Lisp 的代碼含義了。
讓我們看看下面的例子:
1
> 'Hello
2
Hello
3
>
"Hello"
4
"Hello"
5
> _
符號 'Hello
和字符串字面量 "Hello"
不同. 現在你就會明白為什麼在 REPL 中使用雙引號來標注一個字符串,這樣是為了和有著相同字母的符號進行區分。
println
函數可以擁有任意個數的參數。
1
> (println
"Hello"
" World!"
)
2
Hello World!
3
" World!"
4
> _
上面的代碼中,參數一個接一個的合並後,輸出到屏幕,最後一個參數的值作為函數的返回值進行返回給 REPL。
通常,參數是從左到右進行計算的,然後將結果傳遞給函數。傳遞給函數的參數可以說被完全的計算過了,這就是大家所說的應用序求值(applicative-order evaluation).
但是請注意,函數 quote
並不是這樣.
1
> (quote (println
"Hello World!"
))
2
(println
"Hello World!"
)
3
> _
如果它的參數是這個:
1
(println
"Hello World!"
)
如果它被完全解釋後傳遞,我們將會在屏幕上看到:
1
Hello World!
事實並不是這樣,函數 quote
是一種特殊的函數,通常被稱為特殊形式函數 “special form”.
你可以在 newLISP 中設計自己的特殊形式函數,這種函數叫做宏(macro), 它的參數能以字面量被調用。這就是正則序求值(normal-order evaluation),我們說這種順序是惰性的。也就是說,一個宏的參數在傳遞過程中並不會被直接計算(我們將在下面了解具體情況)。
因此,函數 quote
將參數按字面量傳遞並返回。在某種意義上,引用 quote
代表了典型的惰性計算原則。它並不對參數做任何運算,只是單單的按照字面量返回它。
如果沒有特殊形式函數,其他函數中的流程控制,是不能在只有列表語法的語言中實現的。例如,看看下面的 if
函數.
1
> (
if
true
(println
"Hello"
) (println
"Goodbye"
))
2
Hello
3
"Hello"
4
> _
特殊形式函數 if
接受三個參數:
1
語法: (
if
condition consequence alternative)
2
3
condition(條件) =>
true
4
consequence(結果) => (println
"Hello"
)
5
alternative(替代) => (println
"Goodbye"
)
參數 condition
總是被完全的計算,但參數 consequence
和 alternative
的表達式是惰性的。因為參數 alternative
的表達式可能根本不需要計算.
請注意 if
這個表達式. 它返回的值到底是 consequence
還是 alternative
, 依賴於 condition
是真還是假. 在以上的例子中,alternative
表達式沒有後被計算,因為打印到屏幕 “Goodbye” 的副作用永遠都不會出現.
如果一個 if
表達式的條件 condition
表達式測試為假,但又沒有 alternative
語句,那麼它就會返回 nil
. nil
的意思根據不同的環境可能解釋為空值(void)或假(false).
注意:在大多數主流計算機語言中,if
只是一個語句,並不會產生返回值。
如果 Lisp 缺乏這個惰性計算特性,它就無法用來實現特殊形式函數或宏(macro)。如果沒有惰性計算,大量額外的關鍵字 and/or 語法就會不得不加入到語言中。
直到現在,��看到幾種語法?括號和引用?哦,似乎有點少!
惰性計算帶給你的就是,我們自己可以在語言中添加個性化的流程控制方式,來擴展這門語言,訂制自己的專用語言。函數和宏的書寫將在本教程的後面部分。
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-05/102252p2.htm
newLISP 的詳細介紹:請點這裡
newLISP 的下載地址:請點這裡
為Emacs配置newLISP開發環境 http://www.linuxidc.com/Linux/2013-01/78463.htm
newLISP做GitLab系統備份 http://www.linuxidc.com/Linux/2013-01/78464.htm
newLISP 遍歷目錄樹,清理編譯目錄 http://www.linuxidc.com/Linux/2013-08/88954.htm