1.1.6 条件表达式和 判断式子

1.1.6 条件表达式和 判断式子(返回真或假的布尔值)
当前我们能够定义的程序的类型的表达力是很有限的,因为我们还没有进行测试和根据
测试的结果执行不同的操作的方式。例如我们还不能定义一个程序,通过测试一个数的
正,负或者是零来计算一个数的绝对值,根据规则在不同的情况下,执行不同的操作。
       |-->  x  如果 x>0 
|x|= --|-->  0  如果 x=0
       |-->  -x 如果 x<0
上述的组合叫做条件分支,在LISP中有一个特定的定义符来标识这种条件分支的情况。
它叫做cond(它代表条件的意思)它的用法如下:

(define (abs x)
    (cond ((> x 0) x)
          ((= x 0) 0)
   ((< x 0) (- x))
    )
)
条件表达式的通用形式如下:
(cond (<p1> <e1>)
      (<p2> <e2>)
      ...
      (<pn> <en>)
)
符号COND接下来的带括号的表达式(<p1> <e1>)被称为子句,在其中的第一个表达式
是一个判断式子,也就是这个表达式的解释结果是真或者假。

条件表达式的执行如下:
判断式子<p1>首先被执行,如果它的值是假,然后<p2>被执行,如果仍是假,
然后<p3>被执行。这个过程一直持续到有一个判断式子为真时,解释器然后返回
社团的结果表达式的值,作为条件表达式的值。 如果没有任何一个判断式子为真值,
那么条件表达式的值为未定义。

单词判断式子,被程序用来返回真或者假这样的布尔值。求绝对值的程序abs利用了
原生的判断式子,〈,〉和=。 这些判断式子,都需要两个实际参数,测试第一个数
相应地是小于,大于或者是等于第二个数,返回真或假。

写绝对值程序的另一种方式是:
(define (abs x)
   (cond ((< x 0) (- x))
         (else x)
   )
)
用汉语来表达是如果X小于0,返回-X,其它的返回X。
ELSE 是一个特定的定义符,它能在COND的最后的子句中使用。
当前面所有的判断式子都为假时,这个子句返回它的值作为条件表达式的值。

这里还有一种方式来写绝对值的程序:
(define (abs x)
    (if (< x 0)
         (- x)
  x)
)
这里使用了特定的定义符IF,这是一个限定类型的条件表达式应用于只有两种情况的
条件下。一个 “IF”这样的条件表达式的通用形式是
(if <predicate> <consequent> <alternative>)
为了执行一个“IF“这样的条件表达式,解释器开始执行判断式子部分,如果返回真,
解释器执行结果表达式部分并且返回它的值,否则,它执行备选表达式部分并返回值。

此外,例如 <,>,=这些原生的判断子句,有逻辑的组合的操作,让我们能组装成
复合的判断式子,有三种最常用的如下:

(and <e1> ... <en>)
解释器按照从左到右的顺序执行,如果任何一个表达式为假,与表达式的值为假。
剩余的不用执行了。如果所有的子表达式为真,与表达式的值为真。

(or <e1> ... <en>)
解释器按照从左到右的顺序执行,如果任何一个表达式为真,与表达式的值为真。
剩余的不用执行了。如果所有的子表达式为假,与表达式的值为假。

(not <e> )
非表达式的值与 <e>表达式的值相反,如果<e>表达式为真,非表达式为假。
如果<e>表达式为假,非表达式为真。

值得注意的是,and 和or 的特定的定义符,不是程序。因为子表达式并不是有必要
都执行。not 是一个普通的程序。

作为与或非的如何使用的例子,条件为 一个数X在5与10的范围之间的表达为如下的式子:
(and (> x 5) (< x 10))

另一个例子是,我们能够定义一个判断式子来测试一个数是否
大于等于另一个数。表示如下:
(define (>= x y)
    (or (> x y) (= x y)))

或者表示成如下的方式:
(define (>= x y)
    (not (< x y)))

练习1.1
如下有一个表达式的序列。对于任何一个表达式,解释器打印的结果是什么?
假定序列被解释以它表示的顺序。

10
(+ 5 3 4)
(- 9 1)
(/ 6 2)
(+ (* 2 4) (- 4 6))
(define a 3)
(define b (+ a 1))
(+ a b (* a b))
(= a b)
(if (and (> b a) (< b (* a b)))
     b
     a
)

(cond ((= a 4) 6)
      ((= b 4) (+ 6 7 a))
      (else 25)
)

(+ 2 (if (> b a) b a))

(* (cond  ((> a b)  a)
          ((< a b)  b)
          (else -1))
   (+ a 1)
)

练习1.2
把如下的表达式翻译成前缀标识法的表达式。

5+4+(2-(3-(6+4/3)))/3*(6-2)*(2-7)

练习1.3
定义一个程序有三个数作为它的参数,返回最大的两个数的平方的和。
例如 (sum-square 1 2 3) 应该返回13。


练习1.4
注意的是我们的解释模型允许组合程序的操作符是一个复合的表达式。
使用这个规则描述如下的程序的实际执行的行为。

(define (a-plus-abs-b a b)
  ((if (> b 0) + -) a b))

练习1.5
Ben Bitdiddle 已经发明了一个测试来确定他用的解释器是使用应用程序序还是自然序的解释。
他定义了如下的两个程序:

(define (p) (p))
(define (test x y)
        (if (= x 0) 0 y)
)

然后,他解释了如下的表达式:

(test 0 (p))

Ben将注意到的是,一个解释器使用程序序的解释过程,有什么行为?
一个解释器使用自然序的解释过程,有什么行为?解释你的答案。(假定特定的符号If的解释规则在程序序和自然序时是一样的:都是判断式的表达式最先被解释,结果确定于对条件部分的解释或者是对条件的例外部分的解释。)

猜你喜欢

转载自blog.csdn.net/gggwfn1982/article/details/81384669