Scheme 语言概要(上)
guile> (define a (cons 1 (cons 2 (cons 3 '())))) guile> a (1 2 3)
如此,以前定义的 p 又变成了 ("hello" . "good") 这个样子了。
在Scheme语言中如此众多的类型判断功能,使得Scheme语言有着非常好的自省功能。即在判断过程的参数是否附合过程的要求。
guile> (cadr ls) ; 此"点对"对象的cdr的car 2 guile> (cddr ls) ; 此"点对"对象的cdr的cdr (3 4) guile> (caddr ls) ; 此"点对"对象的cdr的cdr的car 3 guile> (cdddr ls) ; 此"点对"对象的cdr的cdr的cdr (4)
由pair类型还可以看出它可以轻松的表示树型结构,尤其是标准的二叉树。
比较运算
这样的话代码在运行时会自动调用Guile来解释执行,标准的文件尾缀是".scm"。
guile> (define x (make-vector 5 6)) guile> x #(6 6 6 6 6) guile> (eq? x x) ; 是同一个对象,所以返回#t #t guile> (define z (make-vector 5 6)) guile> z #(6 6 6 6 6) guile> (eq? x z) ; 不是同一个对象 #f guile> (equal? x z) ; 结构相同,内容相同,所以返回#t #t
(define add5 (lambda (x) (+ x 5)))
列表与pair的关系
回过头来,我们再看看下面的定义:
上面的过程就体现了Scheme语言的参数自省(辨别)能力,'0'是数字型,所以返回notaprocedure;而'+'是一个最基础的操作过程,所以返回isaprocedure。
(define 变量名 值)还有下面的操作:
(- 4) => -4 (/ 4) => 1/4
(null? '()) => #t ; null意为空类型,它表示为 '() ,即括号里什么都没有的符号 (null? 5) => #f (define x 123) 定义变量x其值为123 (symbol? x) => #f (symbol? 'x) => #t ; 此时 'x 为符号x,并不表示变量x的值
变量定义可以用define来定义一个变量,形式如下:
标准的Scheme语言定义中没有多行注释,不过在它的实现中几乎都有。在Guile中就有多行注释,以符号组合"#!"开始,以相反的另一符号组合"!#"结束,其中内容为注释,如:
eq?,eqv?和equal?是三个判断两个参数是否相等的过程,其中eq?和eqv?的功能基本是相同的,只在不同的Scheme语言中表现不一样。
(define p (cons 4 5)) => (4 . 5) (car p) => 4 (cdr p) => 5
有理数型(rational)可以定义为 (define p 3.1415)注意的是,符号组合"#!"和"!#"一定分做两行来写。
算术运算相对独立
guile> (not 1) #f guile> (not (list 1 2 3)) #f guile> (not 'a) #f
(eqv? 34 34) => #t (= 34 34) => #t
五.过程定义过程(Procedure)在Scheme语言中,过程相当于C语言中的函数,不同的是Scheme语言过程是一种数据类型,这也是为什么Scheme语言将程序和数据作为同一对象处理的原因。如果我们在Guile提示符下输入加号然后回车,会出现下面的情况:
它是一个小巧而又强大的语言,作为一个多用途的编程语言,它可以作为脚本语言使用,也可以作为应用软件的扩展语言来使用,它具有元语言特性,还有很多独到的特色,以致于它被称为编程语言中的"皇后"。
(define x (cons 'a (cons 'b (cons 'c (cons 'd '())))))
过程的嵌套定义在Scheme语言中,过程定义也可以嵌套,一般情况下,过程的内部过程定义只有在过程内部才有效,相当C语言中的局部变量。
列表(list)
除了max,min,abs外,还有很多数学运算过程,这要根据你用的Scheme语言的运行环境有关,不过它们大多是相同的。在R5RS中规定了很多运算过程,在R5RS的参考资料中可以很容易找到。
(define x 123) (+ 1 2) (* 4 5 6) (display "hello world")
如:复数型(complex) 可以定义为 (define c 3+2i)
(define square (lambda (x) (* x x)))
由此可见,list是pair的子类型,list一定是一个pair,而pair不是list。
其它实现除了Guile外,Scheme语言的实现还有很多,如:GNU/MIT-Scheme, SCI,Scheme48,DrScheme等,它们大多是开源的,可以自由下载安装使用,并且跨平台的实现也很多。你会发现既有象basic的Scheme语言解释器,也有将Scheme语言编译成C语言的编译器,也有象JAVA那样将Scheme语言代码编译成虚拟机代码的编译器。
下图表示了由pairs定义形成的列表:
(char? #\space) => #t (char? #\newline) => #t 以上两个特殊字符:空格和换行 (char? #\f) => #t 小写字母 f (char? #\;) => #t 分号 ; (char? #\5) => #t 字符 5 ,以上这些都是正确的,所以返回值都是 #t (char? 5) => #f 这是数字 5 ,不是字符类型,所以返回 #f
guile> (define name "tomson") guile> name "tomson" guile> (string-length name) ; 取字符串的长度 6 guile> (string-set! name 0 #\g) ; 更改字符串首字母(第0个字符)为小写字母g (#\g) guile> name "gomson" guile> (string-ref name 3) ; 取得字符串左侧第3个字符(从0开始) #\s
字符型
guile> + #<primitive-procedure +>
Lambda关键字Scheme语言中可以用lambda来定义过程,其格式如下:
Scheme语言中的运算符有:
更多的过程定义
上面定义的过程fun有三个参数,其中第一个参数proc也是一个操作过程(因为在Scheme语言中过程也是一种数据,可以作为过程的参数),另外两个参数是数值,所以会出现上面的调用结果。
从上面的操作中可以看出来,只要not后面的参数不是逻辑型,其返回值均为#f。
(add5 11) => 16
; this is a scheme comment line.
Scheme语言中,数字类型的数据还可以按照进制分类,即二进制,八进制,十进制和十六进制,在外观形式上它们分别以符号组合 #b、 #o、 #d、 #x 来作为表示数字进制类型的前缀,其中表示十进制的#d可以省略不写,如:二进制的 #b1010 ,八进制的 #o567,十进制的123或 #d123,十六进制的 #x1afc 。
我们可以自定义一个简单的过程,如下:
这告诉我们"+"是一个过程,而且是一个原始的过程,即Scheme语言中最基础的过程,在GUILE中内部已经实现的过程,这和类型判断一样,如boolean?等,它们都是Scheme语言中最基本的定义。注意:不同的Scheme语言实现环境,出现的提示信息可能不尽相同,但意义是一样的。
上面的 (lambda(x) (+ x x)) 事实上是简单的过程定义,在后面直接加上操作参数5,得出结果10,这样实现了匿名过程,直接用过程定义来操作参数,得出运算结果。
Scheme语言中的boolean类型只有一种操作:not。其意为取相反的值,即:
(set-car! p "hello") (set-cdr! p "good")
其中特殊字符有:#\space 表示空格符和 #\newline 表示换行符。 与lambda相同的另一种方式在Scheme语言中,也可以不用lambda,而直接用define来定义过程,它的格式为:
二.Scheme语言的标准与实现R5RS (Revised(5) Report on the Algorithmic Language Scheme)
Scheme语言的语法规则的第5次修正稿,1998年制定,即Scheme语言的现行标准,目前大多数Scheme语言的实现都将达到或遵循此标准,并且几乎都加入了一些属于自己的扩展特色。
一.Scheme语言的特点Scheme语言是LISP语言的一个方言(或说成变种),它诞生于1975年的MIT,对于这个有近三十年历史的编程语言来说,它并没有象C++,java,C#那样受到商业领域的青睐,在国内更是显为人知。但它在国外的计算机教育领域内却是有着广泛应用的,有很多人学的第一门计算机语言就是Scheme语言。
以下为常见的类型判断和附加说明:
make-list用来创建列表,第一个参数是列表的长度,第二个参数是列表中添充的内容;还可以实现多重列表,即列表的元素也是列表,如:(list (list 1 2 3) (list 4 5 6))。
函数可以作为值返回
Scheme语言是一种高级语言,和很多高级语言(如python,perl)一样,它的变量类型不是固定的,可以随时改变。
guile> (define a (quote xyz)) ; 定义变量a为符号类型,值为xyz guile> a xyz guile> (define xyz 'a) ; 定义变量xyz为符号类型,值为a guile> xyz a
列表示为: (1 2 3 4)
Scheme语言在类型定义中有比较严格的界定,如在C语言等一些语言中数字0来代替逻辑类型数据False,在Scheme语言中是不允许的。
字符串(string) 由多个字符组成的数据类型,可以直接写成由双引号括起的内容,如:"hello" 。下面是Guile中的字符串定义和相关操作: