newLISP你也行 --- 基礎知識

  #############################################################################
  # 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,這樣的函數就就叫作破壞性函數,好比
  pushreplace .
 
  >(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                                
相關文章
相關標籤/搜索