循环函数中的局部变量
所有的循环函数都使用局部变量,比如doargs, dolist, dostring, dotimes, dotree和 for . 在循环执行期间,每次循环都给变量赋予不同的值. 但在离开循环函数后,变量将恢复其原来的值 。let,define, 和lambda 是另一种声明局部变量的方法:
用let,letn,local 和letex 声明局部变量
let是一种常见的在代码块中申明局部变量的方法.
(define (sum-sq a b)
(let ((x (* a a)) (y (* b b)))
(+ x y)))
(sum-sq 3 4) → 25
; alternative syntax
(define (sum-sq a b)
(let (x (* a a) y (* b b))
(+ x y)))
变量x和y先被初始化,然后执行表达式(+ x y). let 方法其实就是下面语句的优化版本也就是一个语法糖:
((lambda (sym1 [sym2 ...]) exp-body ) exp-init1 [ exp-init2 ...])
当初始化多个参数时, 一个嵌套的 let, letn 就能够使之前初始化过的参数可以被应用到他之后参数的初始化中:
(letn ((x 1) (y (+ x 1)))
(list x y)) → (1 2)
local的工作方式相同,只不过把变量初始化成 nil.
(local (a b c)
... ; expressions using the locale variables a b c
)
letex的工作原理和let类似,不同的是letex将变量在函数体内展开到指定的值。
; assign to local variable and expand in body
(letex ( (x 1) (y '(a b c)) (z "hello") ) '(x y z))
→ (1 (a b c) "hello")
; as in let, parentheses around the initializers can be omitted
(letex (x 1 y 2 z 3) '(x y z)) → (1 2 3)
当离开函数let、letn、local、letex的函数作用域后,声明的局部变量将恢复旧值。
未使用的参数做局部变量
在 newLISP 中, 用户定义函数中的所有参数都是可选的.未使用的参数被赋值为nil,只局限在本函数的局部作用域或动态作用域内。定义比函数需求参数更多的参数用作函数的局部变量,是定义局部变量一个比较方便的方法:
(define (sum-sq a b , x y)
(set 'x (* a a))
(set 'y (* b b))
(+ x y))
逗号不是一种特殊的语法,它只在视觉上将函数参数和局部变量区分开. (从技术上讲逗号, 和 x , y 一样, 也是一个局部变量,被初始化成nil.)
参数默认值
定义函数的时候能够给参数指定默认值:
(define (foo (a 1) (b 2))
(list a b))
(foo) → (1 2)
(foo 3) → (3 2)
(foo 3 4) → (3 4)
用 args 替代 local
使用args函数时,不需要为其定义任何参数符号,args返回一个已经传递的参数列表,但列表不包含已经声明过的参数:
(define (foo)
(args))
(foo 1 2 3) → (1 2 3)
(define (foo a b)
(args))
(foo 1 2 3 4 5) → (3 4 5)
第二个例子中 args 返回的参数值列表,排除了赋值给 a 和 b 的参数值.
通过索引可以访问 (args) 列表:
(define (foo)
(+ (args 0) (args 1)))
(foo 3 4) → 7
使用args和local来命名参数
(define-macro (foo)
(local (len width height)
(bind (args) true)
(println "len:" len " width:" width " height:" height)
))
> (foo (width 20) (height 30) (len 10))
len:10 width:20 height:30
> (foo (width (+ 15 5)) (height 30) (len 10))
len:10 width:20 height:30
> (foo (width (+ 15 5)) (height (* width 2)) (len 10))
len:10 width:20 height:40
local会屏蔽上层作用域对局部作用域中len、widht、height变量值的影响,保持变量在本作用域中的值.