2009/02/06

scheme, Gauche: let、let*、letrec

それぞれの let

let

初期値式が先に評価されて、その後、変数名に束縛される。
初期値式の中で同レベル(同一スコープ)の変数を参照しようとしても、変数は unbound(束縛されていない) variable(変数)となる。
;; let
(let ((a 2)
      (b 3))
  (* a b))
;; => 6


;; nested let
(let ((a 2)
      (b 3))
  (let ((c 4))
    (* a b c)))
;; => 24


;; let with lambda
(let ((a 2)
      (b 3)
      (c (lambda (x y) (* x y))))
  (c a b))
;; => 6


;; cに束縛しようとしているlambda式内からは変数cが見えていない。
;; let with recursion
(let ((a '(1 2 3 4 5))
      (b 2)
      (c (lambda (ls x)
           (if (pair? ls)
               (c (cdr ls) x)
               (print (* (car ls) x))))))
  (c a b))
;; => ERROR: unbound variable: c


letrec

初期値式が評価されるときに同レベル(同一スコープ)の変数が見えている。
ローカルスコープでの再帰が可能。
;; letrec recursion
(letrec ((sum (lambda (ls)
                (cond ((null? ls) 0)
                      ((number? (car ls))(+ (car ls)(sum (cdr ls))))
                      (else (sum (cdr ls)))))))
  (sum '(1 2 3 4 5 6 7 8 9 10)))

P.72 の「ローカルな相互再帰手続き」の例の写経
;; letrec odd adn even double recursion
(letrec ((even? (lambda (n)
                  (cond ((zero? 0) #t)
                        ((> n 0) (odd? (- n 1)))
                        (else (odd? (+ n 1))))))
         (odd? (lambda (n)
                 (cond ((zero? n) #f)
                       ((> n 0) (even? (- n 1)))
                       (else (even? (+ n 1)))))))
  (even? 10))

let*

;; let*
(let* ((a 2)
       (b 3)
       (c (* a a)))
  (* a b c))
;; => 24


;; let* はネストした let と同等
(let ((a 2)
      (b 3))
  (let ((c (* a a)))
    (* a b c)))

Gauche には他にもたくさんの let 系マクロがある。let1, rlet1, if-let1, match-let, let-values, let/cc などなど。


プログラミングGauche

0 件のコメント:

コメントを投稿