The Way 2 Inner Peace.

十诫
又十诫

let,let*和letrec

Qians posted @ 2012年6月18日 16:26 in scheme with tags Scheme , 1556 阅读

在scheme中.let,let*和letrec的形式均写做:(id val-expr).即:

(let ([id val-expr] ...) body ...+),(let* ([id val-expr] ...) body ...+),(letrec ([id val-expr] ...) body ...+)

三者的不同在于,对id及val-expr的运算顺序不同.由此导致的结果也不同.

在let中.先依此所有的计算val-expr.在依此所有的计算id.

在let*中.先计算一个val-expr,将其赋值给id.在进行下一个(id val-expr)的计算.

在letrec中.id首先均为undefined.然后计算所有的val-expr.

由此:

(define foo 5)
;; foo 現在取值 5
(let ((foo 10))
  ;; foo 現在取值 10
  )
;; foo 現在取值 5

这三者的区别在于,let所绑定的变量仅在它的区块内有效,而let*所绑定的变量可以在以下的绑定中使用,例如,

(let* ((var1 10)
       (var2 (+ var1 5)))
  var1)
;; 返回 15
;; 如果僅使用 let,程式會出錯。

letrec所绑定的变量可以互相引用。因此,letrec通常被用于双重递归:

(letrec ((female (lambda(n)
                   (if (= n 0) 1
                       (- n (male (female (- n 1)))))))
         (male (lambda(n)
                 (if (= n 0) 0
                     (- n (female (male (- n 1))))))))
  (display "i male(i) female(i)")(newline)
  (do ((i 0 (+ i 1)))
      ((> i 8) #f)
    (display i) (display "   ")(display (male i))(display "         ")(display (female i))
    (newline)))

(via wikipedia)

 

同时 剥去语法糖.


(let ((x 1))
  (print x))
就是
((lambda (x) (print x)) 1)
 


(letrec ((fact (lambda (x)
                 (if (= x 1)
                    x
                    (* x (fact (- x 1)))))))
  (fact 5))

((lambda (fact x)
   (fact x fact))
(lambda (x fact)
   (if (= x 1)
      x
      (* x (fact (- x 1) fact))))
5)

 

也可以这样:

(letrec ((f (lambda ...))) ...)

就是

(let ((f <undefined>))   (set! f (lambda ...)) ...)


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter