Edited at

オンラインSICP読書女子会 #1(~1.1.6) まとめ

More than 3 years have passed since last update.

#ladiescpp の主催してる オンラインSICP読書女子会 #1 - connpassのまとめです〜。

まちがっているところがあればどんどんコメントください(`・ω・´)ゞ

めも:みんなでGauche使ってます!

他の参加者さんのまとめ等

オンラインSICP読書女子会 #1 (1.1.1~1.1.6) — miumixu's tech blog


1.1.6


練習問題1.1


それぞれの式に対するインタプリタの応答として表示される結果はどうなるか。


> 10

10

> (+ 5 3 4) 

12
;; + は演算子(operator)、 のこりは被演算子(operand)
;; 前置記法の利点の1つとして、任意の数の引数を取る手続きに対応できる

> (- 9 1)

8

> (/ 6 2)

3
> (/ 6 4)
3/2
;; 分数になるのは新鮮なかんじ・・・。
;; 2.2.1にてこれの説明があるそうです!!!

> (define a 3) ;; aを3という値に関連付ける

> (define b (+ a 1))
(= a b)
#f ;false
> (= (+ a 1) b)
#t ;true

;; trueは#t, falseは#f

> (if (and (> b a) (< b (* a b)))

b
a)
4
;; (if ⟨predicate⟩ ⟨consequent⟩ ⟨alternative⟩)
;; 三項演算子みたいな書き方だ〜
;; predicateが先に評価されるのが保証されてる特殊形式

> (cond ((= a 4) 6)

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

;; cond 場合分け(switchみたいなの)
;; (cond (p1 e1)
;; (p2 e2)...)

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

6

> (* (cond ((> a b) a)

((< a b) b)
(else -1))
(+ a 1))
16


めも

;; ゼロ除算

gosh> (/ 5 0)
*** ERROR: attempt to calculate a division by zero

;; condの挙動

gosh> (cond ((print 1) 10) ((print 2) 20) (else 30))
1
10


if と cond

基本的にschemeのインタプリタでは、

演算子、引数(被演算子)すべてが評価されてから、式が評価される。

なので、cond では 全てのcaseが評価される。 -> 練習問題1.6にてもう一度確認

しかし、ifは特殊な構文で、

(if ⟨predicate⟩ ⟨consequent⟩ ⟨alternative⟩)

のうち、predicateを先に評価し、それから

⟨consequent⟩、⟨alternative⟩のどちらを評価するかを決める。


if 式を評価するにあたって、インタプリタは最初に式の ⟨predicate⟩ の部分

を評価します。もし ⟨predicate⟩ の評価結果が真である場合、インタプリタは

⟨consequent⟩ を評価し、その値を返します。そうでなければ ⟨alternative⟩ を評

価し、その値を返します。(19P)


ちなみにandとorも ifのように順番が保証されてる特殊形式。


練習問題1.2


前置記法に書き換える


\frac{5 + 4 + (2 - (3 - (6 + \frac{4}{5}))))}{3(6-2)(2-7)}

(print (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5) ))))

(* 3 (- 6 2) (- 2 7)) ) )
;; -37/150


練習問題1.3


三つの数値を引数として取り、そのうち大きいほう

から二つの数値の二乗の和を返す手続きを定義せよ。


解法1: なんかもっといい感じに書けるはず・・・。

> (define a 1)

> (define b 2)
> (define c 3)

> (define (max x y) ; maxを定義
(cond ((> x y) x)
((<= x y) y) ))
> (max a c)
3
> (define (pow2 x) (* x x)) ; 二乗するのをpow2を定義
> (pow2 b)
4
> (define ans (+ (pow2 a) (pow2 b)))
> (define ans (max ans (+ (pow2 b) (pow2 c))))
> (define ans (max ans (+ (pow2 c) (pow2 a))))
> ans
13

解法2: 再チャレンジ

(define (max x y) (if (> x y) x y)) ;maxを定義

(max 5 2) ;test 5

(define (square x) (* x x)) ;square(二乗)を定義
(square 5) ;test 25

(define (sum-of-squares x y) (+ (square x) (square y)))
(sum-of-squares 3 4) ;test 25

(define (max-sum-of-squares x y z)
(max (max (sum-of-squares x y) (sum-of-squares y z))
(sum-of-squares z x))) ;problem 1.3
(max-sum-of-squares 3 9 5) ;test 106


練習問題1.4


我々の評価モデルでは、演算子が複合式であるよう

な組み合わせが作れるということを観察せよ。この観察結果を使って、次の手続きのふるまいを説明せよ。


(define (a-plus-abs-b a b)

((if (> b 0) + -) a b))
;; 複合手続きは基本手続き(+, -のような組み込みの手続き)と同じように使うことができる
;; (if (> b 0) + -) という複合式が、+ or - の演算子の代わりになってるよね〜という観察`・ω・´)ゞ

> (a-plus-abs-b 5 (- 10))

15


練習問題1.5 (1.1.5 適用順序と正規順序)


  • 適用順序(applicative-order)評価

  • 正規順序(normal-order)評価

一般に利用されている正規順序評価では、完全に展開してから簡約する(上から順番に評価していく)。

適用順序評価(Lispのインタプリタが実際に使っている方法)では、 値が必要になるまで被演算子を評価しない.

(define (p) (p)) 

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

(test 0 (p))

適用順序評価では

test, 0, (p) の全てが評価され、

その後に(test 0 (p))が評価される。

そのため、testがどんな処理であろうと、pは評価されてしまい、自分自身を呼び出し、無限ループに陥る。

正規順序評価の場合は、(p)の評価の前にtestが展開され、

(x = 0) なので testは0を返す。

そのためpは評価されない。