1.1,我用的是kawa,这是用java实现的一个scheme的解释器,kawa(在window下直接双击打开就可以运行)
#|kawa:1|# 10
10
#|kawa:2|# (+ 5 3 4)
12
#|kawa:3|# (- 9 1)
8
#|kawa:4|# (/ 6 2)
3
#|kawa:5|# (+ (* 2 4) (- 4 6))
6
#|kawa:6|# (define a 3)
#|kawa:7|# (define b (+ a 1))
#|kawa:8|# (+ a b (* a b))
19
#|kawa:9|# (= a b)
#f
#|kawa:10|# ((if (and (> b a) (< b (* a b)))
#|(---:11|# b a)
#|(---:12|#
#|(---:13|# ((if (and (> b a) (< b (* a b)))
#|(---:14|# b a)
#|(---:15|# (if (and (> b a) (< b (* a b)))
#|(---:16|#
#|(---:18|# (if (and (> b a) (< b (* a b))) b a)
#|(---:19|# (if (and (> b a) (< b (* a b))) b a)
#|(---:20|# a
#|(---:21|# b
#|(---:22|# a
#|(---:23|# )
#|(---:24|# ))
/dev/stdin:24:3: An unexpected close paren was read.
#|kawa:25|# a
3
#|kawa:26|# b
4
#|kawa:27|# (if (and (> b a) (< b (* a b))) b a)
4
#|kawa:28|# (cond ((= a 4) 6)
#|(---:29|# ((= b 4) (+ 6 7 a))
#|(---:30|# (else 25))
16
#|kawa:39|# (+ 2 (if (> b a) b a))
6
#|kawa:40|# (* (cond ((> a b) a)
#|(---:41|# ((< a b) b)
#|(---:42|# (else -1))
#|(---:43|# (+ a 1))
16
1.2 最简单的可以看到分号看做一个中点,把这个表达式变换成
(/ (5+4+(2-(3-(6+4/5)))) 3(6-2)(2-7))
接下来就每次把这个表达式分成两份
(/ (+ (5+4) (2-(3-(6+4/5))))
(* 3 (6-2) (2-7)))
next:
(/ (+ (+ 5 4) (- 2 (3-(6+4/5))))
(* 3 (- 6 2) (- 2 7)))
next:
(/ (+ (+ 5 4) (- 2 (- 3 (+ 6 (/ 4 5)))))
(* 3 (- 6 2) (- 2 7)))
执行后的值是:
#|kawa:44|# (/ (+ (+ 5 4) (- 2 (- 3 (+ 6 (/ 4 5)))))
#|(---:45|# (* 3 (- 6 2) (- 2 7)))
-37/150
#|kawa:46|#
1.3 这个过程的逻辑就是:在三个数中,随便拿出来一个数x。那么,这个数只有两种结果:是最小的那一个或者是最大的两个数里面的一个。如果他是最小的那一个,那么就把其他的两个数求和;如果不是,那么就取出剩下的两个数里面的大者求和。
(define (max-of-two x y) (if (< x y) y x))
(define (sum-of-bigger-two x y z)
(if (< x y) (+ y (max-of-two x z)) (+ x (max-of-two y z)))) 结果
#|kawa:49|# (define (max-of-two x y) (if (< x y) y x))
#|kawa:50|#(max-of-two 10 10)
10
#|kawa:51|#(max-of-two 10 1)
10
#|kawa:52|# (max-of-two 1 10)
10
#|kawa:53|# (define (sum-of-bigger-two x y z)
#|(---:54|# (if (< x y) (+ y (max-of-two x z)) (+ x (sum-of-bigger-two y z))))
/dev/stdin:54:42: call to 'sum-of-bigger-two' has too few arguments (2; must be 3)
#|kawa:55|# (define (sum-of-bigger-two x y z)
#|(---:56|# (if (< x y) (+ y (max-of-two x z)) (+ x (sum-of-two y z))))
/dev/stdin:56:42: warning - no declaration seen for sum-of-two
#|kawa:57|# (define (sum-of-bigger-two x y z)
#|(---:58|# (if (< x y) (+ y (max-of-two x z)) (+ x (max-of-two y z))))
#|kawa:59|# (sum-of-bigger-two 10 12 1)
22
#|kawa:61|# (sum-of-bigger-two 10 10 1)
20
1.5
(define (p) (p))
(define (test x y)
(if (= x 0)
0
y))
使用表达式(test 0 (p))
如果使用的是应用序求值,那么就是说一个值会在过程被调用之前计算。如果是这样,那么在调用的时候要先计算过程p的值,但是p是一个未定的值,因此会出现异常。
看下面,在kawa中果然如此:
#|kawa:73|# (define (p) (p))
#|kawa:74|# (define (test x y)
#|(---:75|# (if (= x 0)
#|(---:76|# 0
#|(---:77|# y))
#|kawa:78|#(test 0 10)
0
#|kawa:79|# (test 1 10)
10
#|kawa:80|# (test 0 (p))
....(嘿嘿,直接卡死) 另一方面,如果使用的是正则序求值,那么直到过程真正被使用的时候才会出现异常。但是在这个测试过程中,根据if的执行的规则:如果x=0,那么会直接返回0;根本不会用到y,也就不会出现异常。
另外要提一下,我接触的所有的编程语言中,貌似用的都是应用序求值。
本文介绍了使用Java实现的Scheme解释器Kawa,并探讨了计算机程序构造中的基本逻辑。通过实例解析1.3节内容,展示了如何在三个数中找到最小值并进行相应计算,为理解函数式编程语言的思维提供了帮助。
413

被折叠的 条评论
为什么被折叠?



