4. 局部变量 (newLISP 代码模式 v.10.6.2)

循环函数中的局部变量

所有的循环函数都使用局部变量,比如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变量值的影响,保持变量在本作用域中的值.

你可能感兴趣的:(4. 局部变量 (newLISP 代码模式 v.10.6.2))