版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、LISP 語言教程Scheme語言是LISP語言的一個(gè)方言(或說成變種),它誕生于1975年的MIT, 對于這個(gè)有近三十年歷史的編程語言來說,它并沒有象C+, java , C#ffl樣受到商業(yè)領(lǐng)域的青睞,在國內(nèi)更是顯為人知。但它在國外的計(jì)算機(jī)教育領(lǐng)域內(nèi)卻是有著廣泛應(yīng)用的,有很多人學(xué)的第一門計(jì)算機(jī)語言就是Scheme®言。Scheme語言概要Scheme語言是LISP語言的一個(gè)方言(或說成變種),它誕生于1975年的MIT, 對于這個(gè)有近三十年歷史的編程語言來說,它并沒有象C+, java , C#ffl樣受到商業(yè)領(lǐng)域的青睞,在國內(nèi)更是顯為人知。但它在國外的計(jì)算機(jī)教育領(lǐng)域內(nèi)卻是有著廣
2、泛應(yīng)用的,有很多人學(xué)的第一門計(jì)算機(jī)語言就是Scheme®言。作為Lisp變體,Scheme是一門非常簡潔的計(jì)算語言,使用它的編程人員可以擺脫語言本身的復(fù)雜性,把注意力集中到更重要的問題上,從而使語言真正成為解決問題的工具。本文分為上、下兩部分來介紹scheme 語言。一.Scheme語言的特點(diǎn)Scheme語言是LISP語言的一個(gè)方言(或說成變種),它誕生于1975年的MIT, 對于這個(gè)有近三十年歷史的編程語言來說,它并沒有象C+, java , C#ffl樣受到商業(yè)領(lǐng)域的青睞,在國內(nèi)更是顯為人知。但它在國外的計(jì)算機(jī)教育領(lǐng)域內(nèi)卻是有著廣泛應(yīng)用的,有很多人學(xué)的第一門計(jì)算機(jī)語言就是Sche
3、me®言。它是一個(gè)小巧而又強(qiáng)大的語言,作為一個(gè)多用途的編程語言,它可以作為腳本語言使用, 也可以作為應(yīng)用軟件的擴(kuò)展語言來使用,它具有元語言特性,還有很多獨(dú)到的特色, 以致于它被稱為編程語言中的"皇后 "。下面是洪峰對Scheme語言的編程特色的歸納:? 詞法定界(Lexical Scoping )? 動態(tài)類型(Dynamic Typing )? 良好的可擴(kuò)展性? 尾遞歸(Tail Recursive )? 函數(shù)可以作為值返回? 支持一流的計(jì)算連續(xù)? 傳值調(diào)用(passing-by-value )? 算術(shù)運(yùn)算相對獨(dú)立本文的目的是讓有編程基礎(chǔ)(那怕是一點(diǎn)點(diǎn))的朋友能盡
4、快的掌握 Scheme®言 的語法規(guī)則,如果您在讀完本文后,發(fā)現(xiàn)自己已經(jīng)會用 Scheme®言了,那么我 的目的就達(dá)到了。二.Scheme語言的標(biāo)準(zhǔn)與實(shí)現(xiàn)R5RS (Revised(5) Report on the Algorithmic Language Scheme)SchemeSHt的語法規(guī)則的第5次修正稿,1998年制定,即Schemed言的現(xiàn)行標(biāo) 準(zhǔn),目前大多數(shù)Scheme®言的實(shí)現(xiàn)都將達(dá)到或遵循此標(biāo)準(zhǔn),并且?guī)缀醵技尤肓?一些屬于自己的擴(kuò)展特色。Guile (GNU's extension language)Guile是GNU:程的一個(gè)項(xiàng)目,它是
5、 GNUT展語言庫,它也是 Schemed言的一個(gè)具體實(shí)現(xiàn);如果你將它作為一個(gè)庫打包,可以把它鏈接到你的應(yīng)用程序中去,使你的應(yīng)用程序具有自己的腳本語言,這個(gè)腳本語言目前就是Scheme®言。Guile可以在LINUX和一些UNIX系統(tǒng)上運(yùn)行,下面是簡單的安裝過程:下載 guile-1.6.4 版,文件名為guile-1.6.4. ,執(zhí)行下面的命令:tar xvfz guile-1.6.4.cd guile-1.6.4./configuremakemake install如此,即可以執(zhí)行命令guile ,進(jìn)入guile提示符狀態(tài),輸入調(diào)試Scheme®序 代碼了,本文的所有代
6、碼都是在guile 下調(diào)試通過。其它實(shí)現(xiàn) 除了 Guile 外,Schemed言的實(shí)現(xiàn)還有很多,如: GNU/MIT-Scheme SCI , Scheme48 DrSchem好,它們大多是開源的,可以自由下載安裝使用,并且跨 平臺的實(shí)現(xiàn)也很多。你會發(fā)現(xiàn)既有象basic的Scheme語言解釋器,也有將Scheme 語言編譯成C語言的編譯器,也有象JAVA那樣將Scheme語言代碼編譯成虛擬機(jī) 代碼的編譯器。三基本概念 注釋Scheme®言中的注釋是單行注釋,以分號;開始一直到行尾結(jié)束,其中間的內(nèi) 容為注釋,在程序運(yùn)行時(shí)不做處理,如:; this is a scheme comment
7、 line.標(biāo)準(zhǔn)的Scheme®言定義中沒有多行注釋,不過在它的實(shí)現(xiàn)中幾乎都有。在Guile 中就有多行注釋,以符號組合"#!" 開始, 以相反的另一符號組合"!#" 結(jié)束, 其中內(nèi)容為注釋,如:#!there are scheme comment area.you can write mulity lines here . !#注意的是,符號組合"#!" 和 "!#" 一定分做兩行來寫。Scheme用做腳本語言Scheme®言可以象sh, perl , python等語言那樣作為一種腳本語言來
8、使用,用 它來編寫可執(zhí)行腳本,在Linux中如果通過Guile用Scheme語言寫可執(zhí)行腳本, 它的第一行和第二行一般是類似下面的內(nèi)容:#! /usr/local/bin/guile -s !#這樣的話代碼在運(yùn)行時(shí)會自動調(diào)用Guile 來解釋執(zhí)行,標(biāo)準(zhǔn)的文件尾綴是".scm" 。塊 (form)塊(form)是Schemelht中的最小程序單元,一個(gè)Scheme語言程序是由一個(gè)或多個(gè) form 構(gòu)成。沒有特殊說明的情況下form 都由小括號括起來,形如:(define x 123)(+ 1 2)(* 4 5 6)(display "hello world"
9、;)一個(gè) form 也可以是一個(gè)表達(dá)式,一個(gè)變量定義,也可以是一個(gè)過程。form 嵌套Scheme®言中允許form的嵌套,這使它可以輕松的實(shí)現(xiàn)復(fù)雜的表達(dá)式,同時(shí)也是一種非常有自己特色的表達(dá)式。下圖示意了嵌套的稍復(fù)雜一點(diǎn)的表達(dá)式的運(yùn)算過程:(* (+ 2 (* 3 4) (+ 5 6 7)(* (+2 12) (+5 6 7)252至此得出運(yùn)直結(jié)果,可 以看出Schem已語言的 表法式的特點(diǎn)是少了 一些運(yùn)算符,多了很多 對,女號.變量定義可以用define來定義一個(gè)變量,形式如下:(define 變量名值)如:(define x 123),定義一個(gè)變量x,其值為123。更改變量的值可
10、以用set!來改變變量的值,格式如下:(set! 變量名值)如:(set! x "hello") ,將變量 x 的值改為"hello"。Scheme®言是一種高級語言,和很多高級語言(如python , perl) 一樣,它的變 量類型不是固定的,可以隨時(shí)改變。四.數(shù)據(jù)類型1.簡單數(shù)據(jù)類型邏輯型(boolean)最基本的數(shù)據(jù)類型,也是很多計(jì)算機(jī)語言中都支持的最簡單的數(shù)據(jù)類型,只能取兩個(gè)值:#t,相當(dāng)于其它計(jì)算機(jī)語言中的TRUE #f,相當(dāng)于其它計(jì)算機(jī)語言中 的 FALSESchemeShf中的boolean類型只有一種操作:not。其意為取相反
11、的值,即:(not #f) => #t(not #t) => #fnot 的引用,與邏輯非運(yùn)算操作類似guile> (not 1)#fguile> (not (list 1 2 3)#fguile> (not 'a)#f從上面的操作中可以看出來,只要 not 后面的參數(shù)不是邏輯型,其返回值均為#f。數(shù)字型 (number)它又分為四種子類型:整型(integer) ,有理數(shù)型(rational) ,實(shí)型 (real) ,復(fù)數(shù)型(complex) ;它們又被統(tǒng)一稱為數(shù)字類型(number) 。如:復(fù)數(shù)型(complex) 可以定義為(define c 3+2
12、i) 實(shí)數(shù)型(real )可以定義為 (define f 22/7) 有理數(shù)型(rational )可以定義為(define p 3.1415) 整數(shù)型 (integer) 可以定義為(define i 123)Scheme語言中,數(shù)字類型的數(shù)據(jù)還可以按照進(jìn)制分類,即二進(jìn)制,八進(jìn)制,十進(jìn)制和十六進(jìn)制,在外觀形式上它們分別以符號組合#b 、 #o 、 #d 、 #x 來作為表示數(shù)字進(jìn)制類型的前綴,其中表示十進(jìn)制的#d 可以省略不寫,如:二進(jìn)制的#b1010 ,八進(jìn)制的#。567,十進(jìn)制的123或#d123 ,十六進(jìn)制的#x1afc 。Scheme®言的這種嚴(yán)格按照數(shù)學(xué)定理來為數(shù)字類型進(jìn)
13、行分類的方法可以看出Scheme®言里面滲透著很深的數(shù)學(xué)思想,Scheme®言是由數(shù)學(xué)家們創(chuàng)造出來的, 在這方面表現(xiàn)得也比較鮮明。字符型 (char)Scheme®言中的字符型數(shù)據(jù)均以符號組合"#"開始,表示單個(gè)字符,可以是 字母、數(shù)字或"! $ % & * + -. / : < = > ? A _"等等其它字符,如:#A 表示大寫字母A, #0 表示字符0,其中特殊字符有:#space 表示空格符和 #newline 表示換行符。符號型 (symbol)符號類型是Scheme®言中有多種用途的
14、符號名稱,它可以是單詞,用括號括起來的多個(gè)單詞,也可以是無意義的字母組合或符號組合,它在某種意義上可以理解為C中的枚舉類型??聪旅娴牟僮鳎篻uile> (define a (quote xyz) ;定義變量a 為符號類型,值為xyzguile> a xyzguile> (define xyz 'a) ; 定義變量xyz 為符號類型,值為aguile> xyza此處也說明單引號' 與 quote 是等價(jià)的,并且更簡單一些。符號類型與字符串不同的是符號類型不能象字符串那樣可以取得長度或改變其中某一成員字符的值,但二者之間可以互相轉(zhuǎn)換。2. 復(fù)合數(shù)據(jù)類型可以說
15、復(fù)合數(shù)據(jù)類型是由基本的簡單數(shù)據(jù)類型通過某種方式加以組合形成的數(shù)據(jù)類型, 特點(diǎn)是可以容納多種或多個(gè)單一的簡單數(shù)據(jù)類型的數(shù)據(jù),多數(shù)是基于某一種數(shù)學(xué)模型創(chuàng)建的。字符串 (string) 由多個(gè)字符組成的數(shù)據(jù)類型,可以直接寫成由雙引號括起的內(nèi)容,如:"hello" 。下面是Guile 中的字符串定義和相關(guān)操作:guile> (define name "tomson") guile> name"tomson"取字符串的長度更改字符串首字母( 第 0 個(gè)字符 ) 為小寫guile> (string-length name) ;6
16、guile> (string-set! name 0 #g) ;字母 g (#g)guile> name"gomson"guile> (string-ref name 3) ; 取得字符串左側(cè)第3 個(gè)字符(從0 開始)#s字符串還可以用下面的形式定義:guile> (define other (string #h #e #l #l #o )guile> other "hello"字符串中出現(xiàn)引號時(shí)用反斜線加引號代替,如:"abc"def" 。點(diǎn)對 (pair)我把它譯成" 點(diǎn)對 &qu
17、ot; ,它是一種非常有趣的類型,也是一些其它類型的基礎(chǔ)類型,它是由一個(gè)點(diǎn)和被它分隔開的兩個(gè)所值組成的。形如:(1 . 2) 或 (a . b) ,注意的是點(diǎn)的兩邊有空格。這是最簡單的復(fù)合數(shù)據(jù)類型,同是它也是其它復(fù)合數(shù)據(jù)類型的基礎(chǔ)類型,如列表類型( list )就是由它來實(shí)現(xiàn)的。按照Scheme語言說明中的慣例,以下我們用符號組合"=>"來表示表達(dá)式的值。它用 cons 來定義,如:(cons 8 9) =>(8 . 9)其中在點(diǎn)前面的值被稱為car ,在點(diǎn)后面的值被稱為cdr , car 和 cdr 同時(shí)又成為取 pair 的這兩個(gè)值的過程,如:(define
18、 p (cons 4 5) => (4 . 5)(car p)=> 4(cdr p)=> 5還可以用set-car! 和 set-cdr! 來分別設(shè)定這兩個(gè)值:(set-car! p "hello")(set-cdr! p "good")如此,以前定義的p 又變成了("hello" . "good") 這個(gè)樣子了。列表 (list)列表是由多個(gè)相同或不同的數(shù)據(jù)連續(xù)組成的數(shù)據(jù)類型,它是編程中最常用的復(fù)合數(shù)據(jù)類型之一,很多過程操作都與它相關(guān)。下面是在Guile 中列表的定義和相關(guān)操作:guile>
19、; (define la (list 1 2 3 4 )guile> la(1 2 3 4)guile> (length la) ; 取得列表的長度4guile> (list-ref la 3) ;取得列表第3項(xiàng)的值(從0開始)4guile> (list-set! la 2 99) ;設(shè)定列表第2 項(xiàng)的值為9999guile> la(1 2 99 4)guile> (define y (make-list 5 6) ;創(chuàng)建列表guile> y(6 6 6 6 6)make-list 用來創(chuàng)建列表,第一個(gè)參數(shù)是列表的長度,第二個(gè)參數(shù)是列表中添充的內(nèi)容;還
20、可以實(shí)現(xiàn)多重列表,即列表的元素也是列表,如:(list (list 1 2 3)(list 4 5 6)。列表與 pair 的關(guān)系回過頭來,我們再看看下面的定義:guile> (define a (cons 1 (cons 2 (cons 3 '() guile> a(1 2 3)由上可見,a 本來是我們上面定義的點(diǎn)對,最后形成的卻是列表。事實(shí)上列表是在點(diǎn)對的基礎(chǔ)上形成的一種特殊格式。再看下面的代碼:guile> (define ls (list 1 2 3 4)guile> ls(1 2 3 4)guile> (list? ls)#tguile>
21、(pair? ls)#t由此可見,list 是 pair 的子類型,list 一定是一個(gè)pair ,而 pair 不是 list guile> (car ls)1guile> (cdr ls)(2 3 4)其 cdr 又是一個(gè)列表,可見用于pair 的操作過程大多可以用于listguile> (cadr ls) ;2guile> (cddr ls) ;(3 4)guile> (caddr ls) ;3guile> (cdddr ls) ;(4)此 " 點(diǎn)對" 對象的cdr 的 car此 " 點(diǎn)對" 對象的cdr 的 c
22、dr此" 點(diǎn)對" 對象的cdr 的cdr 的car此" 點(diǎn)對" 對象的cdr 的cdr 的cdr上在的操作中用到的cadr, cdddr等過程是專門對PAIR型數(shù)據(jù)再復(fù)合形成的數(shù) 據(jù)操作的過程,最多可以支持在中間加四位a或d,如cdddr, caaddr等。下圖表示了由pairs 定義形成的列表:這個(gè)列表可以由pair定義為如下形式:(define x (cons 'a (cons 'b (cons 'c (cons 'd '()而列表的實(shí)際內(nèi)容則為:(a b c d)由pair類型還可以看出它可以輕松的表示樹型結(jié)
23、構(gòu),尤其是標(biāo)準(zhǔn)的二叉樹。向量(vector )可以說是一個(gè)非常好用的類型,是一種元素按整數(shù)來索引的對象,異源的數(shù)據(jù)結(jié)構(gòu),在占用空間上比同樣元素的列表要少,在外觀上:列表示為:(1 2 3 4) VECTOR表示為:#(1 2 3 4)可以正常定義:(define v(vector 3 4 5)也可以直接定義:(define v #(3 4 5)vector是一種比較常用的復(fù)合類型,它的元素索引從0開始,至第n-1結(jié)束,這一點(diǎn)有點(diǎn)類似C語言中的數(shù)組。關(guān)于向量表(vector )的常用操作過程:guile> (define v (vector 1 2 3 4 5)guile> v#(1
24、 2 3 4 5)guile> (vector-ref v 0); 求第 n 個(gè)變量的值1guile> (vector-length v); 求 vector 的長度5guile> (vector-set! v 2 "abc");設(shè)定 vector 第 n 個(gè)元素的值guile> v#(1 2 "abc" 4 5)guile> (define x (make-vector 5 6);創(chuàng)建向量表guile> x#(6 6 6 6 6)make-vector 用來創(chuàng)建一個(gè)向量表,第一個(gè)參數(shù)是數(shù)量,后一個(gè)參數(shù)是添充的值,這和
25、列表中的make-list 非常相似。我們可以看出,在Schemed言中,每種數(shù)據(jù)類型都有一些基本的和它相關(guān)的操作過程,如字符串,列表等相關(guān)的操作,這些操作過程都很有規(guī)律,過程名的單詞之間都用-號隔開,很容易理解。對于學(xué)過 C+勺朋友來說,更類似于某個(gè)對象的方法,只不過表現(xiàn)的形式不同了。3. 類型的判斷、比較、運(yùn)算、轉(zhuǎn)換與方法類型判斷Scheme®言中所有判斷都是用類型名加問號再加相應(yīng)的常量或變量構(gòu)成,形如:( 類型 ? 變量 )Scheme®言在類型定義中有比較嚴(yán)格的界定,如在 C語言等一些語言中數(shù)字0 來代替邏輯類型數(shù)據(jù)False ,在Scheme®言中是不允
26、許的。以下為常見的類型判斷和附加說明:(boolean? #t) => #t (boolean? #f) => #t (boolean? 2) => #f邏輯型:#t 和 #f 都是 boolean 類型,所以其值為#t2 是數(shù)字類型,所以其值為#f(char? #space) => #t(char? #newline) => #t(char? #f)=> #t(char? #;)=> #t(char? #5)=>回值都是#t(char? 5)=>字符型:以上兩個(gè)特殊字符:空格和換行小寫字母f分號 ;#t 字符 5 ,以上這些都是正確的,所
27、以返#f 這是數(shù)字5 ,不是字符類型,所以返回#f數(shù)字型:(integer? 1)=> #t(integer? 2345) => #t(integer? -90)=> #t以上三個(gè)數(shù)均為整數(shù)(integer? 8.9)=> #f 8.9不整數(shù)(rational? 22/7)=> #t(rational? 2.3)=> #t(real? 1.2)=> #t(real? 3.14159) => #t(real? -198.34)=> #t(real? 23)=> #t(number? 5)=> #t(number? 2.345) =
28、> #t(number? 22/7) => #t以上三個(gè)數(shù)均為實(shí)數(shù)型 因?yàn)檎蛯儆趯?shí)型其它型:(null? '()=> #t ; null意為空類型,它表示為'() ,即括號里什么都沒有的符號(null? 5)=> #f(define x 123)定義變量x其值為123(symbol? x) => #f(symbol?'x)=> #t ;此時(shí)'x 為符號x,并不表示變量x的值 在Scheme®言中如此眾多的類型判斷功能,使彳導(dǎo)Scheme語言有著非常好的自省 功能。即在判斷過程的參數(shù)是否附合過程的要求。比較運(yùn)算Sch
29、eme®言中可以用 <, >, <=, >=,=來判斷數(shù)字類型值或表達(dá)式的關(guān)系,如判斷變量x 是否等于零,它的形式是這樣的:(= x 0) ,如 x 的值為 0 則表達(dá)式的值為 #t ,否則為#f。還有下面的操作:(eqv? 34 34) => #t(= 34 34)=> #t以上兩個(gè)form 功能相同,說明eqv? 也可以用于數(shù)字的判斷。在Scheme®言中有三種相等的定義,兩個(gè)變量正好是同一個(gè)對象;兩個(gè)對象具有相同的值;兩個(gè)對象具有相同的結(jié)構(gòu)并且結(jié)構(gòu)中的內(nèi)容相同。除了上面提到的符號判斷過程和eqv?外,還有eq?和equal?也是判斷
30、是否相等的過程。eq?, eqv? , equal?eq?, eqv?和equal?是三個(gè)判斷兩個(gè)參數(shù)是否相等的過程,其中eq?和eqv?的功能基本是相同的,只在不同的 Scheme®言中表現(xiàn)不一樣。eq?是判斷兩個(gè)參數(shù)是否指向同一個(gè)對象,如果是才返回 #t ; equal?則是判斷兩 個(gè)對象是否具有相同的結(jié)構(gòu)并且結(jié)構(gòu)中的內(nèi)容是否相同,它用eq?來比較結(jié)構(gòu)中成員的數(shù)量;equal? 多用來判斷點(diǎn)對,列表,向量表,字符串等復(fù)合結(jié)構(gòu)數(shù)據(jù)類型。guile> (define v (vector 3 4 5)guile> (define w #(3 4 5) ; w 和 v 都是
31、vector 類型,具有相同的值#(3 45)guile> (eq? v w)#f;此時(shí)w和v是兩個(gè)對象guile> (equal? v w)#t;符合equal?的判斷要求以上操作說明了eq? 和 equal? 的不同之處,下面的操作更是證明了這一點(diǎn):guile> (define x (make-vector 5 6)guile> x#(6 6 6 6 6)guile> (eq? x x) ; 是同一個(gè)對象,所以返回#t#tguile> (define z (make-vector 5 6)guile> z#(6 6 6 6 6)guile>
32、(eq? x z) ; 不是同一個(gè)對象#fguile> (equal? x z) ; 結(jié)構(gòu)相同,內(nèi)容相同,所以返回#t#t算術(shù)運(yùn)算SchemeShf中的運(yùn)算符有:+ , - , *,/ 和expt (指數(shù)運(yùn)算)其中-和/還可以用于單目運(yùn)算,如:(- 4) => -4(/ 4) => 1/4此外還有許多擴(kuò)展的庫提供了很多有用的過程,max 求最大(max 8 89 90 213) => 213min 求最小(min 3 4 5 6 7) => 3abs 求絕對值(abs -7) => 7除了 max, min, abs外,還有很多數(shù)學(xué)運(yùn)算過程,這要根據(jù)你用的S
33、chemeSH!的運(yùn)行環(huán)境有關(guān),不過它們大多是相同的。在R5RS規(guī)定了很多運(yùn)算過程,在R5RS勺參考資料中可以很容易找到。轉(zhuǎn)換Scheme®言中用符號組合"->"來標(biāo)明類型間的轉(zhuǎn)換(很象 C語言中的指針)的 過程,就象用問號來標(biāo)明類型判斷過程一樣。下面是一些常見的類型轉(zhuǎn)換過程:guile> (number->string 123) ;"123"guile> (string->number "456") ;456guile> (char->integer #a) ;數(shù)字轉(zhuǎn)換為字符串字符
34、串轉(zhuǎn)換為數(shù)字字符轉(zhuǎn)換為整型數(shù),小寫字母a 的 ASCII 碼值為 96 97大寫字母A的值為65整型數(shù)轉(zhuǎn)換為字符字符串轉(zhuǎn)換為列表列表轉(zhuǎn)換為字符串字符串轉(zhuǎn)換為符號類型符號類型轉(zhuǎn)換為字符串guile> (char->integer #A) ;65guile> (integer->char 97) ;#aguile> (string->list "hello") ;(#h #e #l #l #o)guile> (list->string (make-list 4 #a) ;"aaaa"guile> (str
35、ing->symbol "good") ;goodguile> (symbol->string 'better) ;"better"五過程定義 過程( Procedure )在Schemed言中,過程相當(dāng)于C語言中的函數(shù),不同的是Scheme®言過程是 種數(shù)據(jù)類型,這也是為什么Scheme®言將程序和數(shù)據(jù)作為同一對象處理的原因。 如果我們在Guile 提示符下輸入加號然后回車,會出現(xiàn)下面的情況:guile> +#<primitive-procedure +>這告訴我們"+”是一個(gè)過
36、程,而且是一個(gè)原始的過程,即Schemed言中最基礎(chǔ)的 過程,在GUILE中內(nèi)部已經(jīng)實(shí)現(xiàn)的過程,這和類型判斷一樣,如 boolean?等, 它們都是Scheme®言中最基本的定義。注意:不同的Scheme®言實(shí)現(xiàn)環(huán)境,出 現(xiàn)的提示信息可能不盡相同,但意義是一樣的。define不僅可以定義變量,還可以定義過程,因在Scheme語言中過程(或函數(shù)) 都是一種數(shù)據(jù)類型,所以都可以通過define 來定義。不同的是標(biāo)準(zhǔn)的過程定義要使用 lambda 這一關(guān)鍵字來標(biāo)識。Lambda關(guān)鍵字Scheme®言中可以用lambda來定義過程,其格式如下:(define 過程名( l
37、ambda ( 參數(shù).) (操作過程.)我們可以自定義一個(gè)簡單的過程,如下:(define add5 (lambda (x) (+ x 5)此過程需要一個(gè)參數(shù),其功能為返回此參數(shù)加5 的值,如:(add5 11) => 16下面是簡單的求平方過程square 的定義:(define square (lambda (x) (* x x)與lambda相同的另一種方式在Schemed言中,也可以不用lambda,而直接用define來定義過程,它的格 式為:(define ( 過程名 參數(shù))(過程內(nèi)容 )如下面操作:(define (add6 x) (+ x 6)add6#<proce
38、dure: add6 (x)> 說明 add6 是一個(gè)過程,它有一個(gè)參數(shù)x(add6 23) => 29再看下面的操作:guile> (define fun(lambda(proc x y)(proc x y)guile> fun#<procedure fun (proc x y)>guile> (fun * 5 6)30guile> (fun / 30 3)10更多的過程定義上面定義的過程fun 有三個(gè)參數(shù),其中第一個(gè)參數(shù)proc 也是一個(gè)操作過程(因?yàn)樵赟cheme語言中過程也是一種數(shù)據(jù),可以作為過程的參數(shù)),另外兩個(gè)參數(shù)是數(shù)值,所以會出現(xiàn)上
39、面的調(diào)用結(jié)果。guile> (define add(lambda (x y)(+ x y)guile> add#<procedure add (x y)>guile> (fun add 100 200)300繼續(xù)上面操作,我們定義一個(gè)過程 add,將add作為參數(shù)傳遞給fun過程,得出 和 (fun + 100 200) 相同的結(jié)果。guile> (lambda (x) (+ x x) 5) 10上面的 (lambda(x) (+ x x) 事實(shí)上是簡單的過程定義,在后面直接加上操作參數(shù)5,得出結(jié)果10,這樣實(shí)現(xiàn)了匿名過程,直接用過程定義來操作參數(shù),得出運(yùn)算
40、結(jié)果。通過上面的操作,相信你已初步了解了過程的用法。既然過程是一種數(shù)據(jù)類型,所以將過程作為過程的參數(shù)是完全可以的。以下過程為判斷參數(shù)是否為過程,給出一個(gè)參數(shù),用procedure? 來判斷參數(shù)是否為過程,采用if 結(jié)構(gòu)(關(guān)于if結(jié)構(gòu)見下面的介紹):guile> (define isp(lambda (x)(if(procedure? x) 'isaprocedure 'notaprocedure)guile> isp#<procedure isp (x)>guile> (isp 0)notaprocedureguile> (isp +)isa
41、procedure上面的過程就體現(xiàn)了 Scheme語言的參數(shù)自省(辨別)能力,'0'是數(shù)字型,所以 返回notaprocedure ; 而 '+' 是一個(gè)最基礎(chǔ)的操作過程,所以返回isaprocedure 。過程的嵌套定義 在Scheme®言中,過程定義也可以嵌套,一般情況下,過程的內(nèi)部過程定義只 有在過程內(nèi)部才有效,相當(dāng)C語言中的局部變量。如下面的代碼的最終結(jié)果是50: (define fix(lambda (x y z)(define add(lambda (a b) (+ a b)(- x (add y z)(display (fix 100 2
42、0 30)此時(shí)過程add 只在 fix 過程內(nèi)部起做用,這事實(shí)上涉及了過程和變量的綁定,可以參考下面的關(guān)于過程綁定(let , let* 和 letrec )的介紹。過程是初學(xué)者難理解的一個(gè)關(guān)鍵,隨著過程參數(shù)的增加和功能的增強(qiáng),過程的內(nèi)容變得越來越復(fù)雜,小括號也會更多,如果不寫出清晰的代碼的話,讀代碼也會成為一個(gè)難題。熟悉了 scheme 基本概念、數(shù)據(jù)類型和過程(函數(shù))后,下一部分我們來學(xué)習(xí)scheme 的結(jié)構(gòu)、遞歸調(diào)用和其他擴(kuò)展功能。六常用結(jié)構(gòu)順序結(jié)構(gòu)也可以說成由多個(gè)form 組成的 form ,用 begin 來將多個(gè)form 放在一對小括號內(nèi),最終形成一個(gè)form。格式為:(begin
43、 forml form2 )如用Scheme語言寫成白經(jīng)典的helloworld 程序是如下樣子的:(begin(display "Hello world!") ;輸出 "Hello world!"(newline);換行if 結(jié)構(gòu)Schemei§言的if結(jié)構(gòu)有兩種格式,一種格式為:(if測試 過程1過程2),即測試條件成立則執(zhí)行過程1,否則執(zhí)行過程2。例如下面代碼:(if (= x 0)(display "is zero")(display "not zero")還有另一種格式:(if 測試 過程 )
44、,即測試條件成立則執(zhí)行過程。例如下面代碼:(if (< x 100) (display "lower than 100")根據(jù)類型判斷來實(shí)現(xiàn)自省功能,下面代碼判斷給定的參數(shù)是否為字符串:(define fun(lambda ( x )(if (string? x)(display "is a string")(display "not a string")如執(zhí)行(fun 123)則返回值為"not a string",這樣的功能在 C+-+E JAVA中實(shí)現(xiàn)的話可能會很費(fèi)力氣。cond 結(jié)構(gòu)SchemeShf
45、中的cond結(jié)構(gòu)類似于 C語言中的switch結(jié)構(gòu),cond的格式為:(cond (測試)操作)(else 操作)如下是在Guile 中的操作:guile> (define w (lambda (x)(cond (< x 0) 'lower)(> x 0) 'upper)(else 'equal)guile> w#<procedure w (x)>guile> (w 9)upperguile> (w -8) lowerguile> (w 0) equal上面程序代碼中,我們定義了過程 w,它有一個(gè)參數(shù)x,如果x的值大
46、于0,則 返回符號upper,如x的值小于0則返回符號lower ,如x的值為0則返回符號 equal 。下載已做成可執(zhí)行腳本的例程。cond 可以用 if 形式來寫,上面的過程可以如下定義:guile> (define ff(lambda (x)(if (< x 0) 'lower(if (> x 0) 'upper 'zero)guile> ff#<procedure ff (x)>guile> (ff 9)upperguile> (ff -9) lowerguile> (ff 0)zero這在功能上是和cond
47、 一樣的,可以看出cond 實(shí)際上是實(shí)現(xiàn)了if 的一種多重嵌套。case 結(jié)構(gòu)case結(jié)構(gòu)和cond結(jié)構(gòu)有點(diǎn)類似,它的格式為:(case ( 表達(dá)式 ) ( 值 ) 操作 ) . (else 操作 )case 結(jié)構(gòu)中的值可以是復(fù)合類型數(shù)據(jù),如列表,向量表等,只要列表中含有表達(dá)式的這個(gè)結(jié)果,則進(jìn)行相應(yīng)的操作,如下面的代碼:(case (* 2 3)(2 3 5 7) 'prime)(1 4 6 8 9) 'composite)上面的例子返回結(jié)果是composite ,因?yàn)榱斜?1 4 6 8 9) 中含有表達(dá)式(* 2 3)的結(jié)果6;下面是在Guile 中定義的func 過程,用
48、到了case 結(jié)構(gòu):guile> (define func(lambda (x y)(case (* x y)(0) 'zero)(else 'nozero)guile> func#<procedure func (x y)>guile> (func 2 3)nozeroguile> (func 2 0)zeroguile> (func 0 9)zeroguile> (func 2 9)nozero可以下載另一個(gè)腳本文件te.scm ,參考一下。and 結(jié)構(gòu)and 結(jié)構(gòu)與邏輯與運(yùn)算操作類似,and 后可以有多個(gè)參數(shù),只有它后面的參
49、數(shù)的表達(dá)式的值都為#t 時(shí),它的返回值才為#t ,否則為 #f ??聪旅娴牟僮鳎篻uile> (and (boolean? #f) (< 8 12)#tguile> (and (boolean? 2) (< 8 12)#fguile> (and (boolean? 2) (> 8 12)#f如果表達(dá)式的值都不是boolean 型的話, 返回最后一個(gè)表達(dá)式的值,如下面的操作:guile> (and (list 1 2 3) (vector 'a 'b 'c)#(a b c)guile> (and 1 2 3 4 )4guil
50、e> (and 'e 'd 'c 'b 'a)aor 結(jié)構(gòu)or 結(jié)構(gòu)與邏輯或運(yùn)算操作類似,or 后可以有多個(gè)參數(shù),只要其中有一個(gè)參數(shù)的表達(dá)式值為#t,其結(jié)果就為#t,只有全為#f時(shí)其結(jié)果才為#f。如下面的操作:guile> (or #f #t)#tguile> (or #f #f)#fguile> (or (rational? 22/7) (< 8 12)#tguile> (rational? 22/7)#tguile> (real? 22/7)#tguile> (or (real? 4+5i) (inte
51、ger? 3.22)#f我們還可以用and和or結(jié)構(gòu)來實(shí)現(xiàn)較復(fù)雜的判斷表達(dá)式,如在 C語言中的表達(dá) (x > 100) && (y < 100) 和 (x > 100) | (y > 100)在Scheme中可以表示為:guile> (define x 123)guile> (define y 80)guile> (and (> x 100) (< y 100)#tguile> (or (> x 100) (> y 100)#tSchemeSHI只有if結(jié)構(gòu)是系統(tǒng)原始提供的,其它的 cond, case,
52、and, or, 另外還有do, when, unless等都是可以用宏定義的方式來定義的,這一點(diǎn)充分 體現(xiàn)了 Scheme勺元語言特性,關(guān)于do, when等結(jié)構(gòu)的使用可以參考 R5RS七.遞歸調(diào)用用遞歸實(shí)現(xiàn)階乘在Scheme®言中,遞歸是一個(gè)非常重要的概念,可以編寫簡單的代碼很輕松的 實(shí)現(xiàn)遞歸調(diào)用,如下面的階乘過程定義:(define factoral (lambda (x)(if (<= x 1) 1(* x (factoral (- x 1)我們可以將下面的調(diào)用(factoral 4),即4的階乘的運(yùn)算過程圖示如下:由小叫目】)的箔,.就(* 4 6)24/一以下為fa
53、ctoral過程在Guile中的運(yùn)行情況:4«* W 1)到此劇3謔用苑苴,因guile> (define factoral (lambda (x) (if (<= x 1) 1 (* x (factoral (- x 1)guile> factoral#<procedure factoral (x)> guile> (factoral 4)24另一種遞歸方式 卜面是一另一種遞歸方式的定義:(define (factoral n)(define (iter product counter)(if (> counter n)product (i
54、ter (* counter product) (+ counter 1)System Message: WARNING/2 (<string>, line 954)Definition list ends without a blank line; unexpected unindent.(iter 1 1)System Message: WARNING/2 (<string>, line 955)Definition list ends without a blank line; unexpected unindent.(display (factoral 4)這個(gè)
55、定義的功能和上面的完全相同,只是實(shí)現(xiàn)的方法不一樣了,我們在過程內(nèi)部實(shí)現(xiàn)了一個(gè)過程iter ,它用 counter 參數(shù)來計(jì)數(shù),調(diào)用時(shí)從1 開始累計(jì),這樣它的展開過程正好和我們上面的遞歸過程的從4 到 1 相反,而是從1 到 4。循環(huán)的實(shí)現(xiàn)在Schemed言中沒有循環(huán)結(jié)構(gòu),不過循環(huán)結(jié)構(gòu)可以用遞歸來很輕松的實(shí)現(xiàn)(在 Scheme®言中只有通過遞歸才能實(shí)現(xiàn)循環(huán))。對于用慣了C語言循環(huán)的朋友,在Scheme中可以用遞歸簡單實(shí)現(xiàn):guile> (define loop(lambda(x y)(if (<= x y)(begin (display x) (display #space
56、) (set! x (+ x 1)(loop x y)guile> loop#<procedure loop (x y)> guile> (loop 1 10)1 2 3 4 5 6 7 8 9 10這只是一種簡單的循環(huán)定義,過程有兩個(gè)參數(shù),第一個(gè)參數(shù)是循環(huán)的初始值,第二個(gè)參數(shù)是循環(huán)終止值,每次增加1。相信讀者朋友一定會寫出更漂亮更實(shí)用的循環(huán)操作來的。八變量和過程的綁定let , let* , letrec在多數(shù)編程語言中都有關(guān)于變量的存在的時(shí)限問題,SchemeiHt中用let , let*和 letrec 來確定變量的存在的時(shí)限問題,即局部變量和全局變量,一般情況下
57、,全局變量都用define 來定義,并放在過程代碼的外部;而局部變量則用let 等綁定到過程內(nèi)部使用。用 let 可以將變量或過程綁定在過程的內(nèi)部,即實(shí)現(xiàn)局部變量:guile> let#<primitive-macro! let>從上面的操作可以看出let 是一個(gè)原始的宏,即guile 內(nèi)部已經(jīng)實(shí)現(xiàn)的宏定義。let 的用法(注意多了一層括號):guile> (let (x 2) (y 5) (* x y)10它的格式是:(let (),下面是稍復(fù)雜的用法:guile> (let (x 5)(define foo (lambda (y) (bar x y)(defi
58、ne bar (lambda (a b) (+ (* a b) a)(foo (+ x 3)45以上是 Guile 中的代碼實(shí)現(xiàn)情況。它的實(shí)現(xiàn)過程大致是:(foo 8) 展開后形成(bar 5 8) ,再展開后形成(+ (* 5 8) 5) ,最后其值為45。再看下面的操作:guile> (let (iszero?(lambda(x)(if (= x 0) #t #f)(iszero? 9)#fguile> (iszero? 0) ; 此時(shí)會顯示出錯(cuò)信息let 的綁定在過程內(nèi)有效,過程外則無效,這和上面提到的過程的嵌套定是一樣的,上面的iszero? 過程在操作過程內(nèi)定義并使用的,操作結(jié)束后再另行引用則無效,顯示過程未定義出錯(cuò)信息。let* 的用法:guile> (let (x 2) (y 5)(let* (x 6)(z (+ x y) ;此時(shí) x 的值已為6,所以z 的值應(yīng)為11,如此最后的值為66(* z x)66還有 letrec ,看下面的操作過程:guile> (letrec (even?(lambda(x)(if (= x 0) #t(odd? (- x 1)(odd?(lambda(x)(if (= x 0) #f(even
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 七年級語文上冊第4單元第20課《雖有佳肴》教學(xué)設(shè)計(jì)及反思(新版)新人教版
- DB 3705T 47-2024黃河口灘區(qū)肉羊繁育技術(shù)規(guī)范
- 二手房買賣合同范本解析
- 個(gè)人與公司委托代繳公積金合同范本
- 中小企業(yè)借款合同模板
- XX公司委托培訓(xùn)合同
- 中鐵物資商城采購合同新范本
- 上海市臨時(shí)勞動合同模板
- 個(gè)人投資入股合同范例
- 不動產(chǎn)行紀(jì)買賣合同書
- 商業(yè)綜合體市場調(diào)研報(bào)告
- 資源枯竭型城市的轉(zhuǎn)型發(fā)展 課件 2024-2025學(xué)年高二上學(xué)期地理人教版選擇性必修2
- 2025屆河北省衡水市衡水中學(xué)高考仿真模擬英語試卷含解析
- 天津市部分區(qū)2023-2024學(xué)年高二上學(xué)期期末考試 生物 含解析
- 變壓器投標(biāo)書-技術(shù)部分
- 小學(xué)一年級數(shù)學(xué)思維訓(xùn)練100題(附答案)
- 法院拍賣議價(jià)協(xié)議書
- 新能源充電站運(yùn)營手冊
- 2024年蘭州新區(qū)實(shí)正鑫熱電有限公司招聘筆試沖刺題(帶答案解析)
- 血透室護(hù)士長述職
- (正式版)JTT 1218.4-2024 城市軌道交通運(yùn)營設(shè)備維修與更新技術(shù)規(guī)范 第4部分:軌道
評論
0/150
提交評論