SICPを読む(24) 1.2.3(3) 局所変数let

やっと「変数」という物が登場しました。

letの書式は

(let
  binds
  body)

もうちょっと詳しく書くと

(let
  ((var exp)
   (var exp)
   ...)
  body)

letの中に囲まれた文が、変数の有効範囲になる。

lambdaのシンタックスシュガーなので、非常にわかりづらい。


では、コーディング。

3つの変数定義を見比べてみる。

define法
; define法
(define (f x y)
  (define (f-helpler a b)
    (+ (* x (square a))
       (* y b)
       (* a b)))
  (f-helpler (+ 1 (* x y))
             (- 1 y)))

慣れた方法。

lambda法
; lambda法
(define (f x y)
  ((lambda (a b)
     (+ (* x (square a))
        (* y b)
        (* a b)))
   (+ 1 (* x y))
   (- 1 y)))

((lambda params body) args)の形。

let法
; let法
(define (f x y)
  (let ((a (+ 1 (* x y)))
        (b (- 1 y)))
    (+ (* x (square a))
       (* y b)
       (* a b))))

(let binds body)の形。

こう見ると、letが一番スッキリ見える。


インデントを揃えた方が見易いかな。

(define (f x y)
  (let 
    ((a (+ 1 (* x y)))
     (b (- 1 y)))
    (+ (* x (square a))
       (* y b)
       (* a b))))

う〜ん。結局、

(define (f x y)
  (define a (+ 1 (* x y)))
  (define b (- 1 y))
  (+ (* x (square a))
       (* y b)
       (* a b)))

defineでいいんでない?(汗

慣れるまで時間がかかりそう・・・。

問題1.34

MzSchemeだとエラーメッセージが不親切なので、gaucheを使った。

gosh> (use slib)(require 'trace)
#<undef>
#t
gosh> (define (f g) (g 2))
f
gosh> (trace f)
#<closure (debug:trace-procedure debug:trace-procedure)>
gosh> (f f)
CALL f #[proc]
 CALL f 2
*** ERROR: invalid application: (2 2)

(f f)→(f 2)→(2 2)

と評価されて、2でエラー。