#############################################################################
# Name:newLISP你也行 --- 基礎知識
# Author:黃登(winger)
# Project:http://code.google.com/p/newlisp-you-can-do
# Gtalk:free.winger@gmail.com
# Gtalk-Group:zen0code@appspot.com
# Blog:http://my.opera.com/freewinger/blog/
# QQ-Group:31138659
# 大道至簡 -- newLISP
#
# Copyright 2012 黃登(winger) All rights reserved.
# Permission is granted to copy, distribute and/or
# modify this document under the terms of the GNU Free Documentation License,
# Version 1.2 or any later version published by the Free Software Foundation;
# with no Invariant Sections, no Front-Cover Texts,and no Back-Cover Texts.
#############################################################################
一. 啓動newLISP
若是你要啓動一個交互式的newLISP(如下簡稱nl)程序,只要在任何一個終端內敲入
newlisp命令就好了.
C:>newlisp
newLISP v.10.4.0 on Win32 IPv4/6 UTF-8, execute 'newlisp -h' for more inf
>
這是後你就能夠方便的測試單條語句了,若是須要測試多條語句.能夠用兩種方法:
1: [cmd]和[/cmd]必須單獨佔一行.
>[cmd]
- (define (fibonacci n)
- (if (< n 2)
1
- (+ (fibonacci (- n 1))
(fibonacci (- n 2)))))
[/cmd]
>
2: 第一行單獨輸入一個回車.
>
- (define (fibonacci n)
- (if (< n 2)
1
- (+ (fibonacci (- n 1))
(fibonacci (- n 2)))))
>(fibonacci 10)
89
除了命令行的nl還能夠啓動圖形界面的newLISP-GS editor,GS是newLISP提供的一個
圖形化工具包.WIN32的啓動方法在上一節有講解,詳細資料請查閱guiserver.lsp.html.
http://newlisp.org/index.cgi?Code_Contributions.同時提供了各類編輯器的配置本
.
二. 三大基本法則
法則 1: 列表是元素的序列:
(Rule 1: a list is a sequence of elements)
(1 2 3 4 5) ; 包含數字的列表
("the" "cat" "sat") ; 包含字符串的列表
(x y z foo bar) ; 包含symbol的列表
(sin cos tan atan) ; 包含newLISP函數的列表
(1 2 "stitch" x sin); 混合列表
(1 2 (1 2 3) 3 4 ) ; 一個列表內包含另外一個列表
((1 2) (3 4) (5 6)) ; 列表的列表
列表是newLISP的基礎結構,同時也是咱們編寫代碼的方式.不過如今先別急着把上面
的數據輸入命令行測試,讓咱們先把剩下的2個法則看完.
法則 2: 列表的第一個元素是特殊的:
(Rule 2: the first element in a list is special)
newLISP會把列表中的第一個元素做爲函數,剩下的元素做爲這個函數的參數.
法則2中的例子均可以輸入命令行測試.
(+ 2 2)
這個列表中友3個元素,函數 + 和緊接其後的 2 個數字.nl在處理完這個列表後返回
4 (of course).
(+ 1 2 3 4 5 6 7 8 9)
返回45,函數 + 把列表中全部的數字都加了起來.
(max 1 1.2 12.1 12.2 1.3 1.2 12.3)
返回12.3,列表中最大的數字 (理論上列表無長度限制).
(print "the sun has put his hat on")
"the sun has put his hat on"
print打印字符串 "the sun has put his hat on" ,同時他的返回值也是他打印的
字符串.這樣你在控制檯console上就會看到重複的2行字符串.
> (println "九黎")
九黎
"\190\197\192\232"
上面是在非utf8版本上的輸出, println 在打印完字符串後還會打印一個換行符.
> (println "軒轅")
軒轅
"軒轅"
這個是在utf8版本上的輸出,utf8版本的好處就是可以正常顯示非ascii的多位字節
文字.
print函數能夠將一系列的數據打印成一條字符串:
> (print 1 2 "buckle" "my" "shoe")
12bucklemyshoe"shoe"
上面的代碼打印了2個數字元素和3個字符串元素.(可使用 format 讓輸出更清晰)
函數 directory 能夠列出指定目錄下的文件.
(directory "/");unix
(directory "c:/");win32
上面的命令能夠打印出系統根目錄下的文件列表.若是不指定任何參數,則列出當前
目錄下的全部文件.
>(real-path);獲取當前目錄的絕對路徑
"C:\\Program Files\\newlisp"
> (real-path "newlisp_manual.html");獲取指定文件的絕對路徑
"C:\\Program Files\\newlisp\\newlisp_manual.html"
>(real-path ".");
"C:\\Program Files\\newlisp"
read-file 函數用來讀取文本文件:
(read-file "/usr/share/newlisp/modules/stat.lsp");unix
(read-file "C:\\Program Files\\newlisp\\util\\link.lsp");win32
在某些狀況爲了讓輸出更美觀也能夠用 println 打印出結果.
(println (read-file "/usr/share/newlisp/modules/stat.lsp"))
在咱們看第三個法則前,讓咱們看一個更有用的東西.
嵌套列表
前面咱們已經看到了很多,一個列表中出現另外一個列表的狀況.你是否是有點疑惑呢?
> (* (+ 1 2) (+ 3 4))
21
當newLISP遇到這個列表的時候,他的處理順序是這樣的:
首先他看到了第一個元素 * ,把他做爲一個函數,接着他要收集剩下的元素做爲參數
.但是他遇到了另外一個列表:
(+ 1 2)
nl果斷暫停了以前的工做,進入這個列表裏,開始處理這個列表,這個列表的結果就是
3.很簡單(不懂得同窗找個地方畫圈圈去--!).
好了又回到剛纔第一層列表,繼續爲函數 * 收集參數,這時候又遇到了一個列表:
(+ 3 4)
nl一樣很是果斷的處理完了這個列表,又獲得一個結果7.
這時候兩個內部的列表都計算出告終果,他們變成了下面的樣子:
(* 3 7)
這下nl很是滿意,再也沒有嵌套列表了,一切都 "和諧" 了,多清晰啊.
nl計算出了最後結果21,並將他們返回給咱們.
這個過程以下:
(* (+ 1 2) (+ 3 4))
(* (+ 1 2) 7)
(* 3 7)
21
從第一行的6個括號,到第四行的0個括號,nl有條不紊的完成了全部的工做.
不少同窗也許開始迷惑了,這怎麼和咱們平時用的語言和計算的方法不對啊,嘿嘿.其
實最真實的編譯器原型就是這樣滴,而別的語言作的就是把你們平時寫的表達式分解成上
面的這種形式,再作進一步的計算.固然若是你實在不習慣這樣,nl也提供了內部函數,讓
你改變語法,這樣你能夠把nl假裝成任何你喜歡的program language.
當讓若是你入門之後,你會發現這纔是最正常的一種方式,那些說括號bt的人,10個有
10個是沒有真正學習lisp的.
不論是從語法仍是編碼來講,括號都不是什麼問題.
也許你會擔憂若是寫了好幾層括號會不會迷糊了?對於這個問題個人建議是:
<1> 括號層不能太多,不少人是三層之後再也不加,把多餘的功能分散到別的函數去.
<2> 用個好點的編輯器.win的筆記本確定是不行,太掉價了,會嚴重影響形象.Emacs這樣
的你們夥我就不說了,基本上N多語言都有model,很強大很和諧.VIM嘛,這個既快又小.還
有notepad++,這個不少人說好啊,不過那個語法文件我整不出來,無視我吧.scite我只用
這個,沒啥說的,誇平臺,小巧,界面簡單.除了我須要的功能,其餘的都不加,須要強大的能
只要編寫下lua腳本就好了.如今只要正常點得編輯器,都具備括號自動匹配.在好點得還
有自動完成,指定提示.在scite裏你按Ctrl+E就會跳到前括號對應的後括號,Ctrl+Shift+
E能夠選取括號內的內容.同時配上代碼摺疊和context.一切都會很輕鬆,基本不會出現,
混亂.而你們只是須要先熟悉下這種函數前置的編碼習慣就行了.
記住,故事永遠不會只有一個版本.
括號就像一個思想容器,你能夠加入任何東西,而你須要提取思想的時候,只要給他加
如另外一個括號.(固然你也能夠當作宇宙,太極,陰陽,天地......)
法則 3:引號阻止計算:
(Quoting prevents evaluation)
要阻止nl計算就用單引號括起來.
比較下面兩行:
(+ 2 2)
'(+ 2 2)
第二個列表前面多了個單引號.讓咱們測試看看.
> (+ 2 2)
4
>'(+ 2 2)
(+ 2 2)
>
第一個例子,和前面同樣,nl像日常同樣,把第一個參數 + 做爲函數,將後面兩個參數
加起來,返回數字4.
第二個例子,nl看到了單引號 ' ,直接就講後面的列表做爲數據返回了,根本就不計
算了.
若是說第一個例子就像一個靜止的宇宙,那單引號能作得就是copy整個宇宙,並把他
做爲數據返回給你,這樣你就擁有了一個不會動的宇宙.固然你宇宙還能夠轉動起來.
在什麼狀況下咱們須要阻止列表的 "內部" 計算呢?
當你存儲數據到列表中的時候.
(2012 4 1) ; 今天的年/月/日
("winger" "黃登") ; 某人的名字
咱們不但願 2012 或者"winger" 被當作函數.由於他們都不是真的函數,也不多是
真的函數,函數不能用數字或者雙引號開頭,不然nl會提示錯誤.因此咱們須要用到單引號
.
'(2012 4 1) ; 計算成 (2012 6 1)
'("winger" "黃登") ; 計算成 ("winger" "黃登")
其實單引號是函數quote的縮寫形式:
> '(2012 4 1)
(2012 4 1)
> (quote (2012 4 1))
(2012 4 1)
> (= ' quote)
true
記住他能夠阻止後面列表的 "內部" 計算.
Symbols 和 引號
(Symbols and quotes)
什麼是Symbol?
靈魂,符文...
這個東西不翻譯,很差翻譯,記住就行了,畢竟沒幾個關鍵字.翻譯過來還彆扭.
Symbol就像一個個靈魂,一個靈魂一個裝下一個宇宙,一個宇宙內又有千千萬萬個宇
宙.靈魂的力量是強大的,世界全部的東西都能裝下,而Symbol也是強大的,任何數據都能
裝下,他就像個容器.又像個標誌.若是實在要類比,他和別的語言中變量很相像.
>(define alphabet "abcdefghijklmnopqrstuvwxyz")
"abcdefghijklmnopqrstuvwxyz"
>(set 'alphabet "abcdefghijklmnopqrstuvwxyz");這只是set的語法要求
"abcdefghijklmnopqrstuvwxyz"
>(setf alphabet "abcdefghijklmnopqrstuvwxyz")
"abcdefghijklmnopqrstuvwxyz"
上面三條語句乾的活是同樣的,建立一個symbol,並把英文字母表賦值給他.
如今只要有語句調用, alphabet 就被自動計算成26個字母的字符串.當讓你不能在
他前面加上單引號.
>(upper-case alphabet)
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
由於咱們須要用到alphabet的值,因此咱們沒有給他加上單引號,不然傳遞給
upper-case 的就是一個symbol名了,咱們要得是symbol值.歐了沒?
newLISP並不像別的語言那樣頻繁的使用symbol來保存值.由於nl的哲學就是,代碼即
數據,數據即代碼.這樣的結果就是代碼更短,寫的更爽.
>(println (first (upper-case alphabet)))
"A"
upper-case 將返回值傳遞給 first 函數, first 函數再將返回值傳遞給println ,
打印出來.
固然仍是有不少地方要用到symbol的:
(define x (+ 2 2 ))
(define y ’(+ 2 2))
>(define x (+ 2 2 ))
4
第一行咱們沒有使用單引號,nl想日常同樣計算(+ 2 2) ,而後把返回值4賦值給x.
>(define y '(+ 2 2))
(+ 2 2)
第二行咱們使用了單引號,這樣nl就把這個list (+ 2 2) 賦值給了y(並不計算).
>x
4
>y
(+ 2 2)
>'y
y
最後這個'y 就是symbol名. 而上面那個則是symbol值.
三. 破壞性函數
(Destructive functions)
在nl內部,有的函數會改變操做的symbol,這樣的函數就就叫作破壞性函數,好比
push 和 replace .
>(setf m 25)
25
>(+ m 1)
26
>m
25 ;m沒有改變仍然是25
>(inc m)
26
>m
26 ;m被改變了,inc就被稱爲破壞性函數,若是要用這樣的函數又不想改變原來的symbol
;你就要這樣寫:(inc (copy m))
o了吃飯去.
2012-04-02 21:33:27
html 彩色版本請看 http://code.google.com/p/newlisp-you-can-do