Scheme 语言概要(上)

作为Lisp 变体,Scheme 是一门非常简洁的计算语言,使用它的编程人员可以摆脱语言本身的复杂性,把注意力集中到更重要的问题上,从而使语言真正成为解决问题的工具。本文分为上、下两部分来介绍 scheme 语言。

一.Scheme语言的特点

Scheme语言是LISP语言的一个方言(或说成变种),它诞生于1975年的MIT,对于这个有近三十年历史的编程语言来说,它并没有象C++,java,C#那样受到商业领域的青睐,在国内更是显为人知。但它在国外的计算机教育领域内却是有着广泛应用的,有很多人学的第一门计算机语言就是Scheme语言。

它是一个小巧而又强大的语言,作为一个多用途的编程语言,它可以作为脚本语言使用,也可以作为应用软件的扩展语言来使用,它具有元语言特性,还有很多独到的特色,以致于它被称为编程语言中的"皇后"。

下面是洪峰对Scheme语言的编程特色的归纳:

  • 词法定界(Lexical Scoping)
  • 动态类型(Dynamic Typing)
  • 良好的可扩展性
  • 尾递归(Tail Recursive)
  • 函数可以作为值返回
  • 支持一流的计算连续
  • 传值调用(passing-by-value)
  • 算术运算相对独立

本文的目的是让有编程基础(那怕是一点点)的朋友能尽快的掌握Scheme语言的语法规则,如果您在读完本文后,发现自己已经会用Scheme语言了,那么我的目的就达到了。

二.Scheme语言的标准与实现

R5RS (Revised(5) Report on the Algorithmic Language Scheme)

Scheme语言的语法规则的第5次修正稿,1998年制定,即Scheme语言的现行标准,目前大多数Scheme语言的实现都将达到或遵循此标准,并且几乎都加入了一些属于自己的扩展特色。

Guile (GNU's extension language)

Guile是GNU工程的一个项目,它是GNU扩展语言库,它也是Scheme语言的一个具体实现;如果你将它作为一个库打包,可以把它链接到你的应用程序中去,使你的应用程序具有自己的脚本语言,这个脚本语言目前就是Scheme语言。

Guile可以在LINUX和一些UNIX系统上运行,下面是简单的安装过程:

下载guile-1.6.4版,文件名为guile-1.6.4.tar.gz,执行下面的命令:


tar xvfz guile-1.6.4.tar.gz
cd guile-1.6.4
./configure
make
make install

如此,即可以执行命令guile,进入guile>提示符状态,输入调试Scheme程序代码了,本文的所有代码都是在guile下调试通过。

其它实现

除了Guile外,Scheme语言的实现还有很多,如:GNU/MIT-Scheme, SCI,Scheme48,DrScheme等,它们大多是开源的,可以自由下载安装使用,并且跨平台的实现也很多。你会发现既有象basic的Scheme语言解释器,也有将Scheme语言编译成C语言的编译器,也有象JAVA那样将Scheme语言代码编译成虚拟机代码的编译器。

三.基本概念

注释

Scheme语言中的注释是单行注释,以分号[;]开始一直到行尾结束,其中间的内容为注释,在程序运行时不做处理,如:


  ; this is a scheme comment line.
  

标准的Scheme语言定义中没有多行注释,不过在它的实现中几乎都有。在Guile中就有多行注释,以符号组合"#!"开始,以相反的另一符号组合"!#"结束,其中内容为注释,如:


#!
there are scheme comment area.
you can write mulity lines here . 
!#

注意的是,符号组合"#!"和"!#"一定分做两行来写。

Scheme用做脚本语言

Scheme语言可以象sh,perl,python等语言那样作为一种脚本语言来使用,用它来编写可执行脚本,在Linux中如果通过Guile用Scheme语言写可执行脚本,它的第一行和第二行一般是类似下面的内容:

#! /usr/local/bin/guile -s
!#

这样的话代码在运行时会自动调用Guile来解释执行,标准的文件尾缀是".scm"。

块(form)

块(form)是Scheme语言中的最小程序单元,一个Scheme语言程序是由一个或多个form构成。没有特殊说明的情况下 form 都由小括号括起来,形如:


(define x 123)
(+ 1 2)
(* 4 5 6)
(display "hello world")

一个 form 也可以是一个表达式,一个变量定义,也可以是一个过程。

form嵌套

Scheme语言中允许form的嵌套,这使它可以轻松的实现复杂的表达式,同时也是一种非常有自己特色的表达式。下图示意了嵌套的稍复杂一点的表达式的运算过程:

image001.png

变量定义

可以用define来定义一个变量,形式如下:
(define 变量名 值)

如: (define x 123) ,定义一个变量x,其值为123。

更改变量的值

可以用set!来改变变量的值,格式如下:
(set! 变量名 值)

如: (set! x "hello") ,将变量x的值改为"hello" 。

Scheme语言是一种高级语言,和很多高级语言(如python,perl)一样,它的变量类型不是固定的,可以随时改变。

四.数据类型

1. 简单数据类型

逻辑型(boolean)

最基本的数据类型,也是很多计算机语言中都支持的最简单的数据类型,只能取两个值:#t,相当于其它计算机语言中的 TRUE;#f,相当于其它计算机语言中的 FALSE。

Scheme语言中的boolean类型只有一种操作:not。其意为取相反的值,即:

  (not #f) => #t
  (not #t) => #f
  

not的引用,与逻辑非运算操作类似


guile> (not 1)
#f
guile> (not (list 1 2 3))
#f
guile> (not 'a)
#f

从上面的操作中可以看出来,只要not后面的参数不是逻辑型,其返回值均为#f。

数字型(number)

它又分为四种子类型:整型(integer),有理数型(rational),实型(real),复数型(complex);它们又被统一称为数字类型(number)。

如:复数型(complex) 可以定义为 (define c 3+2i)
实数型(real)可以定义为 (define f 22/7)
有理数型(rational)可以定义为 (define p 3.1415)
整数型(integer) 可以定义为 (define i 123)

Scheme语言中,数字类型的数据还可以按照进制分类,即二进制,八进制,十进制和十六进制,在外观形式上它们分别以符号组合 #b、 #o、 #d、 #x 来作为表示数字进制类型的前缀,其中表示十进制的#d可以省略不写,如:二进制的 #b1010 ,八进制的 #o567,十进制的123或 #d123,十六进制的 #x1afc 。

Scheme语言的这种严格按照数学定理来为数字类型进行分类的方法可以看出Scheme语言里面渗透着很深的数学思想,Scheme语言是由数学家们创造出来的,在这方面表现得也比较鲜明。

字符型(char)

Scheme语言中的字符型数据均以符号组合 "#" 开始,表示单个字符,可以是字母、数字或"[ ! $ % & * + - . / : %lt; = > ? @ ^ _ ~ ]"等等其它字符,如:
#A 表示大写字母A,#表示字符0,
其中特殊字符有:#space 表示空格符和 #newline 表示换行符。

符号型(symbol)

符号类型是Scheme语言中有多种用途的符号名称,它可以是单词,用括号括起来的多个单词,也可以是无意义的字母组合或符号组合,它在某种意义上可以理解为C中的枚举类型。看下面的操作:


guile> (define a (quote xyz))  ;  定义变量a为符号类型,值为xyz
guile> a
xyz
guile> (define xyz 'a)  ; 定义变量xyz为符号类型,值为a
guile> xyz
a

此处也说明单引号' 与quote是等价的,并且更简单一些。符号类型与字符串不同的是符号类型不能象字符串那样可以取得长度或改变其中某一成员字符的值,但二者之间可以互相转换。

2. 复合数据类型

可以说复合数据类型是由基本的简单数据类型通过某种方式加以组合形成的数据类型,特点是可以容纳多种或多个单一的简单数据类型的数据,多数是基于某一种数学模型创建的。

字符串(string) 由多个字符组成的数据类型,可以直接写成由双引号括起的内容,如:"hello" 。下面是Guile中的字符串定义和相关操作:


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> (define other (string #h #e #l #l #o ))
guile> other
"hello"

字符串中出现引号时用反斜线加引号代替,如:"abc"def" 。

点对(pair)

我把它译成"点对",它是一种非常有趣的类型,也是一些其它类型的基础类型,它是由一个点和被它分隔开的两个所值组成的。形如: (1 . 2) 或 (a . b) ,注意的是点的两边有空格。

这是最简单的复合数据类型,同是它也是其它复合数据类型的基础类型,如列表类型(list)就是由它来实现的。

按照Scheme语言说明中的惯例,以下我们用符号组合 "=>" 来表示表达式的值。

它用cons来定义,如: (cons 8 9) => (8 . 9)

其中在点前面的值被称为 car ,在点后面的值被称为 cdr ,car和cdr同时又成为取pair的这两个值的过程,如:


(define p (cons 4 5)) => (4 . 5)
(car p)   => 4
(cdr p)   => 5

还可以用set-car! 和 set-cdr! 来分别设定这两个值:


(set-car! p "hello")
(set-cdr! p "good")

如此,以前定义的 p 又变成了 ("hello" . "good") 这个样子了。

列表(list)

列表是由多个相同或不同的数据连续组成的数据类型,它是编程中最常用的复合数据类型之一,很多过程操作都与它相关。下面是在Guile中列表的定义和相关操作:


guile> (define la (list 1 2 3 4 ))
guile> la
(1 2 3 4)
guile> (length la)  ; 取得列表的长度
4
guile> (list-ref la 3)  ; 取得列表第3项的值(从0开始)
4
guile> (list-set! la 2 99)  ; 设定列表第2项的值为99
99
guile> la
(1 2 99 4)
guile> (define y (make-list 5 6))  ;创建列表
guile> y
(6 6 6 6 6)

make-list用来创建列表,第一个参数是列表的长度,第二个参数是列表中添充的内容;还可以实现多重列表,即列表的元素也是列表,如:(list (list 1 2 3) (list 4 5 6))。

列表与pair的关系

回过头来,我们再看看下面的定义:


guile> (define a (cons 1 (cons 2 (cons 3 '()))))
guile> a
(1 2 3)

由上可见,a本来是我们上面定义的点对,最后形成的却是列表。事实上列表是在点对的基础上形成的一种特殊格式。

再看下面的代码:


guile> (define ls (list 1 2 3 4))
guile> ls
(1 2 3 4)
guile> (list? ls)
#t
guile> (pair? ls)
#t

由此可见,list是pair的子类型,list一定是一个pair,而pair不是list。


guile> (car ls)
1
guile> (cdr ls)
(2 3 4)

其cdr又是一个列表,可见用于pair的操作过程大多可以用于list。


 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)

 

上在的操作中用到的cadr,cdddr等过程是专门对PAIR型数据再复合形成的数据操作的过程,最多可以支持在中间加四位a或d,如cdddr,caaddr等。

下图表示了由pairs定义形成的列表:

image003.png

这个列表可以由pair定义为如下形式:


[@more@]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/8503278/viewspace-890783/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/8503278/viewspace-890783/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值