既然下定決心學習LISP,我計劃學習LISP的過程都以部落格的形式做總結。當然是需要參考學習網上的教程,網上的教程講解的比較詳細。而我打算以自己的了解來做盡可能簡潔的總結,一方面将自己的學習過程做一個回顧,另一方面,如果日後忘記了什麼知識點,也友善查詢。
一、LISP—程式結構
首先lisp很獨特的一點就是圓括号,程式自始至終都是圓括号,例如函數、表達式……這一特色的功能與Java的花括号“{}”和Python的縮進功能類似。LISP的字首表示方法類似于棧的概念,即a+b,寫作(+ a b),下面第一句就是實作(3+5)/2,值得注意的是運算符和數字之間必須以空格間隔開,這是最基本的文法要求。
(print (/ (+ 3 5) 2))
(format t "~%");列印一個換行符
(write-line "Hello World!");最經典的,列印“Hello World!”
二、LISP—基本文法
這裡需要記住的是LISP的三個基本塊:原子、清單和字元串。原子可以了解成編譯器視角下的單一進制素,可以由數字、字母和特殊字元組成。而清單是包含原子與子清單的序列。字元串是由雙引号括起的字元。
需要注意的是1.LISP語言不區分大小寫;
2.過去調用函數的方式為f(x),而在LISP的世界一切都是平等的,寫作(f x);
3.隻有三種類型的元素是常數,傳回的是自己的值:數字;字母t,代表邏輯真;nil,代表邏輯假,還有一個空的清單。
LISP允許名字裡包含數字,但是也别過分到都是數字,這樣編譯器隻能認為這是數字了好吧。之前說原子裡可以包含特殊字元,比如什麼雙引号、冒号什麼的,那麼也需要有轉義字元的,轉義字元是()。
最後值得一提的,先看代碼:
(write (* 2 3));這行代碼會列印出乘法結果6,而如果要列印出(* 2 3),也就是不進行求值,那可以通過以下代碼實作
(write ' (* 2 3));沒錯,就是加一個單引号在前面~~其實想實作這個功能還有一種辦法的
(format t "(* 2 3)");最傳統的列印字元串的好吧,其實也就是列印原子或清單的字面結果。
三、LISP—資料類型
類型說明符是資料類型的系統定義的符号。
array | fixnum | package | simple-string |
atom | float | pathname | simple-vector |
bignum | function | random-state | single-float |
bit | hash-table | ratio | standard-char |
bit-vector | integer | rational | stream |
character | keyword | readtable | string |
[common] | list | sequence | [string-char] |
compiled-function | long-float | short-float | symbol |
complex | nill | signed-byte | t |
cons | null | simple-array | unsigned-byte |
double-float | number | simple-bit-vector | vector |
沒有什麼可說的,類型說明符也隻能等以後遇見什麼再聊吧。先看幾行代碼吧:
(setq a 10)
(print a);前一句可以了解成a是10的變量引用,這裡列印了a
(setq b 20)
(print (type-of b));
輸出結果為
(INTEGER 0 281474976710655)
很顯然這裡輸出的b的類型,而後面的兩個數代表的是b的值在這個範圍内,後面那個數肯定是有背景的,換算成十六進制即為FFFF FFFF FFFF ,可以嘗試一下當輸入為
(setq x 281474976710656) ;建構一個符号指定一個值
(setq x 281474976710657)
(print (type-of x));分别運作上面的代碼,得到的都是 (INTEGER (281474976710655)) ,即是變量的值大于這個臨界值。
四、LISP—宏
我覺得這裡的宏完全可以當做函數對待,宏的定義是使用defmacro來實作的。
;宏定義
(defmacro setTo10(num)
(setq num 10)
(print num))
(setq x 25)
(print x)
(setTo10 x)
五、LISP—變量
全局變量是通過defvar來定義的,而局部變量有三種結構可以建立:setq、let和prog
(defvar x 123)
;(print x)
(write x)
(setq x 10)
(setq y 20)
(format t "x = ~2d y = ~2d ~%" x y);類似于C語言的形式,大概了解是令t指向總字元串
(format t "x = ~2d y = ~2d " x y);“~%”是換行作用,~2d是兩位整型數
;局部變量的使用,分别定義的x、y和z之間不互相沖突
(let ((x ' a)
(y ' b)
(z ' c))
(format t "x = ~a ~% y = ~a ~% z = ~a ~%" x y z))
(prog ((x ' (a b c))
(y ' (1 2 3))
(z ' (p q 10)))
(format t "x = ~a ~% y = ~a ~% z = ~a" x y z));~b是輸出二進制編碼,~a是輸出字元
六、LISP—常量
常量通過defconstant聲明得到,defun即是定義函數。
;聲明圓周率為全局常量,定義一個得到圓面積的函數
(defconstant PI 3.141592)
(defun area-cirlce(rad)
(terpri)
(format t "Radius = ~5f" rad)
(format t "~%Area = ~10f" (* PI rad rad)))
(area-cirlce 10)
七、LISP—運算符
運算符是一個符号,它告訴編譯器執行特定的數學或邏輯操作。其中對資料的運算操作歸類為四種:算術運算、比較操作、邏輯運算和位運算。
算術運算:
運算符 | 描述 | Example |
---|---|---|
+ | 增加了兩個操作數 | (+ A B) = 30 |
- | 從第一數減去第二個操作數 | (- A B)= -10 |
* | 乘兩個操作數 | (* A B) = 200 |
/ | 通過取消分子除以分子 | (/ B A) = 2 |
mod,rem | 模運算符和其餘整數除法後 | (mod B A ) = 0 |
incf | 遞增運算符,所指定的第二個參數增加整數值 | (incf A 3) = 13 |
decf | 遞減操作符,通過指定的第二個參數減小整數值 | (decf A 4) = 9 |
比較操作:
Operator | 描述 | Example |
---|---|---|
= | 檢查如果操作數的值都相等與否,如果是的話那麼條件為真。 | (= A B)= true. |
/= | 檢查如果操作數的值都不同,或沒有,如果值不相等,則條件為真。 | (/= A B) =true. |
> | 檢查如果操作數的值單調遞減。 | (> A B) !=true. |
< | 檢查如果操作數的值單調遞增。 | (< A B) = true. |
>= | 如有左操作數的值大于或等于下一個右操作數的值,如果是則條件檢查為真。 | (>= A B) !=true. |
<= | 如有左操作數的值小于或等于其右操作數的值,如果是,則條件檢查為真。 | (<= A B) = true. |
max | 它比較兩個或多個參數,并傳回最大值。 | (max A B) 傳回20 |
min | 它比較兩個或多個參數,并傳回最小值。 | (min A B) 傳回 20 |
布爾值邏輯操作:
運算符 | 描述 | 示例 |
---|---|---|
and | 這需要任意數量的參數。該參數是從左向右計算。如果所有參數的計算結果為非零,那麼最後一個參數的值傳回。否則就傳回nil。 | (and A B) = NIL. |
or | 這需要任意數量的參數。該參數是從左向右計算的,直到一個計算結果為非零,則此情況下傳回參數值,否則傳回nil。 | (or A B) = 5. |
not | 它接受一個參數,并傳回t,如果參數的計算結果為nil。 | (not A) = T. |
對數位運算操作:
操作符 | 描述 | Example |
---|---|---|
logand | 這将傳回位邏輯的參數和。如果沒有給出參數,則結果為-1,這是該操作的辨別。 | (logand a b)) = 12 |
logior | 這将傳回位邏輯包括它的參數或。如果沒有給出參數,那麼結果是零,這是該操作的辨別。 | (logior a b) = 61 |
logxor | 這将傳回其參數的按位邏輯異或。如果沒有給出參數,那麼結果是零,這是該操作的辨別。 | (logxor a b) = 49 |
lognor | 這不傳回的逐位它的參數。如果沒有給出參數,則結果為-1,這是該操作的辨別。 | (lognor a b) = -62, |
logeqv | 這将傳回其參數的逐位邏輯相等(也稱為異或非)。如果沒有給出參數,則結果為-1,這是該操作的辨別。 | (logeqv a b) = -50 |
這裡就隻給出算術運算和比較運算的代碼,其中對數位運算就是以二進制數之間進行與、或、異或等操作,然後運算的結果以十進制的形式輸出。
;運算符,算術運算
(setq a 10)
(setq b 20)
(format t "~%和:~d" (+ a b))
(format t "~%差:~d" (- a b))
(format t "~%積:~d" (* a b))
(format t "~%商:~d" (/ a b))
(format t "~%取餘:~d" (mod a b))
(format t "~%取餘2:~d" (rem a b))
(format t "~%加的和:~d" (incf a 3))
(format t "~%減的差:~d" (decf a 5))
;比較運算
(format t "~%是否相等? ~a" (= a b))
(format t "~%是否不等? ~a" (/= a b))
(format t "~%是否小于? ~a" (< a b))
(format t "~%是否大于? ~a" (> a b))
(format t "~%是否大于等于? ~a" (>= a b))
(format t "~%是否小于等于? ~a" (<= a b))
(format t "~%最大值? ~a" (max a b 15 30))
(format t "~%最小值? ~a" (min a b 15 30))