一汁三菜

自分が楽しいと思うこと、マラソン、旅行、その他日々の記録をしたい。

1.1.6 Conditional Expressions and Predicates

まずはcond。

(cond (predicate-1 expression-1)
      (preficate-2 expression-2)
      ...
      (else expression-otherwise))

predicate-1を評価して#tなら、expression-1を評価して終了。#fならpredicate-2を評価して、#tならexpression-2を評価。#fなら…。もし全てのpredicate-nが#fを返したら、expression-otherwiseを評価する。predicate-nはたかだか1つ以上あればよく、elseは省略可能。
次はif。

(if predicate then-clause else-clause)

predicateを評価して#tなら、then-clauseを評価、#fならelse-clauseを評価する。
後は、and, or, notなどの論理演算、<, >, <=, >=, =などの比較があった。notは1引数だけど、他は多引数をとる事が可能。

Exercise 1.1

  • 10
  • 12
  • 8
  • 6
  • a
  • b
  • 19
  • #f
  • 4
  • 16
  • 6
  • 16

(define a 3)を評価した結果、aと表示されるのか3と表示されるのかが分からなかった。Gaucheで評価してみたら "a" と表示された。少し考えてみて、a自体は評価されていないんだから、a自体が表示されるんだなと分かった。実際、その後にGaucheでaを評価してみたら、3と表示された。
とはいえ、ここでは(define a 3)がどう表示されるのかは本質的な事じゃなくて、後々の問題の準備として使いたいだけなんだろうけど。

Exercise 1.2

画像中の文字が潰れていて読めないんだけど、多分

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

まだ括弧の対応を目で追わないと、括弧を閉じる時に困る。「コッカ」を自動補完してくれるようなエディタを使えばいいだけなんだけど。

Exercise 1.3

(define (square x) (* x x))
(define (ex13 a b c)
  (+ (square
       (cond
         ((and (> a b) (> a c)) a)
         ((and (> b a) (> b c)) b)
         ((and (> c a) (> c b)) c)))
     (square
       (cond
         ((and (> a b) (> a c)) (if (> b c) b c))
         ((and (> b a) (> b c)) (if (> a c) a c))
         ((and (> c a) (> c b)) (if (> a b) a b))))))

かなり悩んだ。最初はaとb, bとc, cとaで(+ (* x x) (* y y))を求めて、その中の最大値を求めればいいと思ってた。でもそうすると、(ex13 -1 -2 -3) みたいに負数が入ってきた時にダメになる。結局、真面目に1番大きい数と2番目に大きい数を抽出して、それに対して (+ (* x x) (* y y)) を求めるというやり方に落ち着いた。
もっとスマートな書き方があるんだろうけどなあ。

Exercise 1.4

例示されているコードを見てまずびっくらこいた。そうか、procedureもfirst-class objectだから、こんな事が出来るんだなー。
答えは、bが正ならば加算を、負なら減算をするoperatorを適用している、という位で大丈夫かな。

Exercise 1.5

pはそれ自身が無限再帰に陥るprocedure。normal-order evaluationの時は、(test 0 (p))を評価する時に、testを評価する前にpを評価するので、無限再帰に陥る。一方applicative-order evaluationの時は、ifで(= x 0)が真となるので、y (=(p))が評価される事は無い。従って、無限再帰に陥る事は無く、普通に式の評価は終了する。