勉強ノート - SICP(1)

 さて、方法序説だけ読んでても意味がないので、「計算機プログラムの構造と解釈」も読み始めましたよー。
 いやー、Amazonの書評で「翻訳がウンコだ」みたいな事が書いてありますが、全然普通に読めるじゃないですか。ドスエフスキーやカーの翻訳モノに比べれば遙かに読みやすいッス。


三つの棺 (ハヤカワ・ミステリ文庫 カ 2-3)

三つの棺 (ハヤカワ・ミステリ文庫 カ 2-3)

重要かなと思ったキーワード

  • 正規順序、作用的順序
  • 基本式、組み合わせ法、抽象化法

 勉強にはUbuntu+Gaucheでやってます。VPCの中です。これわざわざ(display …)とかやらないと色々出てこないのかなー?超面倒なんだけど。色々調べてみよう。

問題と考察

 ※青字はコメントです。

問題1.1

 それぞれの式で解釈系が印字する結果は何か。

10
;; 10

(+ 5 3 4)
;; 12

(- 9 1)
;; 8

(/ 6 2)
;; 3

(+(* 2 4)(- 4 6))
;; 6

(define a 3)
;; a (中身は3)

(define b (+ a 1))
;; b (中身はa+1=4)

(+ a b (* a b))
;; 3 + 4 + (12) = 19

(= a b)
;; aにbを代入するのかと思った・・・。
;; (a == b)で#f(=false)になるだけ。

(if(and(> b a)
       (< b (* a b))
   ) b a)
;; (b > a && b < a * b) == trueなのでbがでる。4

(cond((= a 4) 6)
     ((= b 4) (+ 6 7 a))
     (else 25))
;; a==4がfalseでb==4がtrueなので6+7+a -> 16

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

(* (cond((> a b) a)
        ((< a b) b)
        (else - 1))
   (+ a 1))
;; b * (a + 1) -> 16
問題1.2

 次の式を前置記法に翻訳せよ。
\frac{5+4+(2-(3-(6+\frac{4}{5})))}{3(6-2)(2-7)}

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

 三つの数を引数として取り、大きい二つの数の二乗の和を返す手続きを定義せよ。
 これは考えている間に、相当カオスになった・・・。普通にCとかで書いてもダメになりそう(汗。へたれですから。

(define (f x y z)(
    if  (> x y)  (if(> y z) (+ (* x x) (* y y))
                            (+ (* x x) (* z z)))
                 (if(> x z) (+ (* x x) (* y y))
                            (+ (* y y) (* z z)))
        )
)

 間違ってないけどスマートじゃない気がする。ググるとだいたいみんなこの方法に似たり寄ったり。(よくわからんから直球で・・・みたいな)
 海外の情報をググったところ、いろんな方法が見つかったよ!

(define (sum-of-two-larger a b c)
  (if (> a b)
      (+ a (if (> b c) b c))
      (+ b (if (> a c) a c))))

 ↑Drink! Girls! Feck! Arse!
 直球型より少し賢い。

(define (ex3 x y z)
    (+ (square (max x y)) (square (max (min x y) z))))

 ↑4chan
 なんだよsquareって。なんだよmax、minて(涙。
 4chanでも「SICP doesn't even mention min and max at that point.」(本的にmaxやminはまだ言及されてないぞ)ってツッコミが入ってます。

(define (ex3 x y z)
   (- (+ (square x) (square y) (square z)) (square (min x y z))))

 ↑同じく4chan
 この発想はなかった。しかし、この問題はセンス丸見えですな。

問題 1.4

 次の手続きの振る舞いは?

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

 なんでもありかよ・・・。恐るべしScheme
 bが正なら加算。負だと減算になるんだけど負の値を減算する事になる。結果 a+|b| をしてる。

問題 1.5

 次の手続きは作用的順序の場合と正規順序の場合、それぞれどうなる?

(define (p) (p))

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

(test 0 (p))

 pがおかしなな事に!!
 これって展開できるのか?(p)とかやったら即死しそうなんだけど。
 実験してみよう。・・・やっぱり止まった。無限ループしてるっぽく感じる。
 つまり

(if (= 0 0) 0 (p))

 こう展開されていないって事だよね。つーことはGaucheは作用的順序で展開したって事ですね。
 答えとしては

  • 正規順序の場合:(if (= 0 0) 0 (p))で0が返る
  • 作用的順序の場合:(test 0 (p))で(p)を展開しようとして死ぬ

テンションあがる!

 問題1.3の別の解を探しているときが一番楽しかった!この調子でどんどん勉強するぞっ
 最初はカッコだらけでどうなるかと思ったけど、自分でやってみたらどうという事はなかったなー。