2006年9月6日星期三

对变量、函数、局部、全局等概念的肤浅认识

对变量、函数、局部、全局等概念的肤浅认识
qjchen
前段时间论坛有过一个函数变量的讨论,让我感触颇深
最近又编了一个很长很长的代码,
因此对变量,函数,局部,全局等概念觉得有必要比较认真的反思一下

于是,做了如下的一些测试,得到了一些体会
由于我是业余编程,本来就是靠蛮劲在编程的,二来Lisp这种语言的函数和变量是同一概念,搞得自己也比较模糊
因此得到的这些看法很肤浅,各位可能早就思考过了,见笑见笑
各位可以先看代码,估算一下结果,假如各位估算全对的话,就完全不用看了,都是很简单的东西

1)当一个函数没有终结的时候,这个函数内的局部变量可以被其他子程序所调用。
这个问题的范例代码是:
[code]
(defun c:test (/ a b)
(setq a 1
b 2
)
(fun 0 1)
)

(defun fun (x y)
(+ (+ x a) (+ y b))
)
[/code]
我原来一直以为中途跑出test去fun中,局部变量会丢失,现在看起来是错误的。
只要这个程序没有终结,里面的各种变量都存在内存空间,只有程序终结了,变量才被清空。

2)在defun里面的定义为局部变量的defun函数不能被其他函数调用
这个问题的范例代码是:
[code]
(defun c:test ()
(setq x (ee 2))
)

(defun fun1 ()
(defun ee (x)
(+ x 6)
)
)
[/code]
可以看出是没有结果的,以前不大明白为什么要把一段那么长的defun写在别的defun里面,
现在觉得可能有些作用,起码这些函数不会和别的变量或者函数同名,而且可能也起到节省内存空间的作用。
这个可以通过在命令行输入!fun1和!ee来认知

3)其实Lisp里面的函数和变量几乎都是一样的,可能这就是Lisp的本质吧,一种表结构的语言
[code]
(defun c:test (/ x)
(setq x (fun1 5))
(princ "\n x = ") (princ x);Erase_DV
(getstring "\nPress Enter to continue...");Erase_DV
(setq xx (eee 6))
(princ "\n xx = ") (princ xx);Erase_DV
(getstring "\nPress Enter to continue...");Erase_DV
)

(defun fun1 (y)
(defun eee (x)
(+ x 6)
)
(eee y)
)
[/code]
可以看出,是都有结果的,所以呢,刚才(2)中提到的defun中的defun不能被其他程序调用的情况要加适用条件了
这个适用条件就是“局部变量”
在这个例子中,假如先调用eee的话是不行的,但是先调用了fun1之后,eee由于不是fun1的局部变量,
就存在了内存空间了,没有被清除

4)传递变量在函数终结时被清空
[code]
;;---------------------------------
(defun c:test ()
(setq a 5
b 6
)
(setq c (fun2 1 2))
(princ "\n a = ") (princ a);Erase_DV
(princ "\n b = ") (princ b);Erase_DV
(getstring "\nPress Enter to continue...");Erase_DV

)
(defun fun2 (a b)
(princ "\n a = ") (princ a);Erase_DV
(princ "\n b = ") (princ b);Erase_DV
(getstring "\nPress Enter to continue...");Erase_DV
(list (+ a 1) (+ b 2))
)
[/code]
可以看出fun2中的a b在fun2结束之后就不复存在了,所以传递变量只是临时存在这个引用函数中,与其他变量同名也无妨


5)总结
在写了上面一堆东西之后,好像突然间想通了,又好像白写了,这个应该就是认知的曲折过程吧
只要掌握了---Lisp中变量和函数是等同的,局部变量(函数)在函数结束后才被清空,全局变量则在关闭图形时清空,
传递变量不影响同名变量 这几个原则,理解起来就轻松一些了。
一时间的乱写,不对之处请指正。
我也会继续做测试。