UP | HOME

局部变量

Table of Contents

在本节中将介绍局部变量,这将会使 定义函数变得更加容易

let 表达式

使用 let 表达式 可以 定义局部变量 。格式如下:

(let binds body)
  • 变量 :在 binds定义的形式 中被 声明并初始化
  • body :由 任意多个 S-表达式 构成

binds的格式如下:

[binds] → ((p1 v1)
	   (p2 v2) ...)

声明了变量 p1 、 p2 ,并分别为它们赋初值 v1 、 v2 ...... 
    声明局部变量 i 和 j,将它们与1、2绑定,然后求二者的和
(let ((i 1) (j 2))
  (+ i j)) ; 3 

let 表达式 可以 嵌套使用

    例如:声明局部变量 i 和 j ,并将分别将它们与 1 和 i+2 绑定,然后求它们的乘积
(let ((i 1))
  (let ((j (+ i 2)))
    (* i j))) ; 3

变量的 作用域(Scope)为body体 ,也就是说 变量只在body中有效 。下列代码会产生错误,因为 在变量 j 的作用域中没有变量 i 的定义

(let ((i 1)
      (j (+ i 2)))
  (* i j)) ;  i: undefined

let* 表达式 可以用于 引用定义在同一个绑定中的变量 。实际上, let* 只是 嵌套的 let表达式 的语法糖 而已

(let* ((i 1)
       (j (+ i 2)))
  (* i j)) ;  3
    函数 quadric-equation 用于计算二次方程

    它需要三个代表系数的参数:a、b、c (ax^2 + bx + c = 0)

    返回一个存放答案的实数表

    通过逐步地使用let表达式,可以避免不必要的计算
;;;The scopes of variables d,e, and f are the regions with the same background colors.
(define (quadric-equation a b c)
  (if (zero? a)      
      'error                                      ; 1
      (let ((d (- (* b b) (* 4 a c))))            ; 2
        (if (negative? d)
            '()                                      ; 3
            (let ((e (/ b a -2)))                    ; 4
              (if (zero? d)
              (list e)
              (let ((f (/ (sqrt d) a 2)))        ; 5
                (list (+ e f) (- e f)))))))))

(quadric-equation 3 5 2)  ; (-2/3 -1) 

这个函数的行为如下:

  1. 如果二次项系数 a 为0,函数返回 'error
  2. 如果a ≠ 0,则将变量 d 与判别式 (b2 - 4ac) 的值绑定
  3. 如果 d 为 负数,则返回 '()
  4. 如果 d 不为 负数,则将变量 e 与 -b/2a 绑定
  5. 如果 d 为 0,则返回一个包含 e 的表
  6. 如果 d 是正数,则将变量 f 与 √(d/2a) 绑定,并返回由 (+ e f) 和 (- e f) 构成的表

词法闭包

实际上, let 表达式 只是 lambda 表达式的一个语法糖

(let ((p1 v1) (p2 v2) ...) exp1 exp2 ...)

=>

((lambda (p1 p2 ...)
    exp1 exp2 ...) v1 v2)

lambda表达式 用于 定义函数 ,它为 变量建立了一个作用域

在 Scheme 中,这个有效域由源代码的编写决定,这叫做 词法闭包 ( lexical closure )

Next:重复

Previous:分支

Home:目录