很久之前买了SICP这本书,一直没怎么看,这两天刷CS61A的lab的时候,刚好看到这门课后半学期讲到了LISP,所以也顺便学习了一下scheme语法。scheme语法十分简单,但是备受推崇的函数式编程的核心不在语法上,而在于只用过程而不用状态来计算这一思想,现在我对此还不是很理解,之后有时间再慢慢啃一下这本书。这里暂时记一下语法好了。
scheme中一共有两类expression,一种是self-evaluationg,比如数字、布尔值
3,5.5,-10,#t,#f
一类是symbol,比如
+,modulo,list,x,foo,hello-world
scheme中主要的结构为procedure,也就是由括号括起来的,可以表示定义
(define x 5)
运算
(+ 2 3)
等。注意,在scheme中,operator要在最前面,然后后面跟着一个或者多个operand。
要为一个name定义一个value,则
(define <name> <expr>)
比如
(define x (+ 3 4))
定义一个function
(define (<name> <param1> <param2> ...) <body>)
或者用一个lambda procedure
(lambda (<param1> <param2> ...) <body>)
比如
((lambda (x) (+ x 2)) 5)
7
条件控制语句,可以用if,也可以用cond
(if <predicate> <if-true> [if-false])
(cond (<pred1> <expr1>) (<pred2> <expr2>) ... (else <else-expr>))
scheme中同样有list,可以用
(list 1 2 3)
(1 2 3)
也可以用quote,具体格式为
(quote <expr>)
或
'<expr>
比如
(quote (1 2 (+ 1 2)))
就不会运行这个procedure,而是直接得到
(1 2 (+ 1 2))
scheme中,对于list结构有内置procedure:map、filter、reduce,分布式计算中的mapreduce就是从这来的,比如
(map (lambda (x) (* x x)) '(1 2 3 4))
(1 4 9 16)
(filter even? '(5 6 7 8))
(6 8)
(reduce + '(9 10 11 12))
42
然后有几个简单的lab,稍微写一下。
Q1:给定x和y,若x小于y则返回-1,等于返回0,大于返回1。
(define (over=or-under x y)
(cond ((< x y) -1)
((= x y) 0)
((> x y) 1)))
Q2:给定一个数num,返回一个procedure,这个procedure对接收到的x返回x+num。
(define (make-adder num)
(lambda (x) (+ x num)))
Q3:给定两个procedure f和g,对这两个procedure输入同样的数x, 返回f接收g接收x后的结果的结果。
(define (composed f g)
(lambda (x) (f (g x))))
pairs是scheme中的基本数据结构,有两个元素,可以用cons来构造
>(define a (cons 2 3))
a
>a
(2 . 3)
>(car a)
2
>(cdr a)
3
在交互界面中,pairs表示为由一个’.'间隔的两个元素。
用多个pairs,可以构造出list
>nil
()
>(define lst (cons 1 (cons 2 (cons 3 nil))))
lst
>lst
(1 2 3)
>(car lst)
1
>(cdr lst)
(2 3)
>(car (cdr lst))
2
>(cdr (cdr (cdr lst)))
()
通常在pairs中,用单个’.‘间隔car和cdr,但是若’.‘后面有左括号时,则省略这个’.’,比如
>(cons 1 (cons 2 3))
(1 2 . 3)
>(cons 1 (cons 2 (cons 3 nil)))
(1 2 3)
在第一个中,2和3之间的’.‘无法省略,但是在第二个中,由于空list nil有左括号,因此最终结果不含’.’。另外,也有
>(cons 5 '(6 7 8))
(5 6 7 8)
即将一个list作为cdr。
注意在scheme中,list也是引用传递,即
(define list1 list2)
后,对list1的操作,list2结果也改变。
可以用以上procedure自己实现list的map操作:
(define (map proc lst)
(if (null? lst)
nil
(cons (proc (car lst))
(map proc (cdr lst)))))