复杂的操作当然就涉及到如何操作过程了,过程与数据的地位是一样的,所以过程的使用就变化多端,学会各种操作过程的方法也就掌握了Scheme的精华。
Scheme的常用结构有:
顺序结构,形如(begin form1 form2 …),入门程序helloworld为
(begin (display "Hello world!") (newline))
if结构,共有2中,(if 测试 过程1 过程2)用法与C语言中的?:类似,另一种为(if 测试 过程),测试成立则执行过程。
cond结构,与C中的switch类似,(cond ((测试) 操作) … (else 操作)).
case结构,(case (表达式) ((值) 操作)) ... (else 操作)))
and结构,即逻辑与,(and (表达式) (表达式) ...)只有它后面的参数的表达式的值都为#t时,它的返回值才为#t,否则为#f。
or结构与and类似。
下面说一下Scheme中重要的递归,以阶乘为例:
(define factoral (lambda (x) (if (<= x 1) 1 (* x (factoral (- x 1)))))) 我们知道任何递归都是可以转化为迭代的,这么看一下迭代的版本,(define (factoral n) (define (iter product counter) (if (> counter n) product (iter (* counter product) (+ counter 1)))) (iter 1 1)) (display (factoral 4))C语言中大家很熟悉循环,但是这里是没有实现循环的,循环的实现需要借助于递归。(define loop (lambda(x y) (if (<= x y) (begin (display x) (display #\\space) (set! x (+ x 1)) (loop x y)))))变量的作用域,C中我们是通过{}来界定的,这里全局变量会放在代码的外部,用define定义,局部变量则使用let来绑定了。格式为(let ((…)…) …),注意这里多了一层括号。
在Scheme中,本地变量除了let
,还有let*
,与letrec
产生。这三者的区别在于,let
所绑定的变量仅在它的区块内有效,而let*
所绑定的变量可以在以下的绑定中使用
(let* ((var1 10) (var2 (+ var1 5))) var2) ;; 返回 15 ;; 如果仅使用 let,会出错。letrec
所绑定的变量可以互相引用。因此,letrec
通常被用于双重递归。 apply的功能是为数据赋予某一操作过程,它的第一个参数必需是一个过程,随后的其它参数必需是列表。(apply + (list 2 3 4))map的功能和apply有些相似,它的第一个参数也必需是一个过程,随后的参数必需是多个列表,返回的结果是此过程来操作列表后的值。(map + (list 1 2 3) (list 4 5 6))Scheme中输入输出涉及到端口的概念,判断是否为输入输出端口,可以用下面两个过程:input-port? 和output-port?
open-input-file,open-output-file,close-input-port,close-output-port这四个过程用来打开和关闭输入输出文件,其中打开文件的参数是文件名字符串,关闭文件的参数是打开的端口。
打开一个输入文件后,返回的是输入端口,可以用read过程来输入文件的内容:
(define port (open-input-file "readme")) (read port)
还可以用load过程来直接调用Scheme语言源文件并执行它,格式为:(load "filename"),还有read-char过程来读单个字符等等。
常用的输出过程是display,还有write,它的格式是:(write 对象 端口),这里的对象是指字符串等常量或变量,端口是指输出端口或打开的文件。