打造随机访问的LISP可变长数组
本帖最后由 vectra 于 2015-12-2 20:58 编辑LISP语言没有指针和引用,有时实在是不太方便,请看这个LISP可变长数组
;; 定义一个可以容纳len个数据的数组
(defun array-def (len uid / ar i)
(setq i 0)
(repeat len
(setq ar (cons (read (strcat uid (itoa i))) ar)
i(1+ i)
)
)
(list uid (reverse ar))
)
;; 销毁数组对象并释放内存
(defun array-clear (ar /)
(foreach e (cadr ar)
(set e nil)
)
)
;; 为数组指定索引位置赋值,成功返回值,失败返回nil
(defun array-set (ar i val / uid)
(setq uid (car ar))
(if (and (>= i 0) (< i (length (cadr ar))))
(set (read (strcat uid (itoa i))) val)
)
)
;; 获取数组指定索引位置值
(defun array-get (ar i / uid)
(setq uid (car ar))
(if (and (>= i 0) (< i (length (cadr ar))))
(vl-symbol-value (read (strcat uid (itoa i))))
)
)
;; 返回数组的容量
(defun array-length (ar /)
(length (cadr ar))
)
;; 重新设置数组的容量
(defun array-set-length (ar len / count uid i tmp)
(setq uid (car ar)
count (array-length ar)
)
(cond
((< len count)
(setq ar (cadr ar))
(repeat len
(setq tmp (cons (car ar) tmp)
ar (cdr ar)
)
)
(foreach e ar
(set e nil)
)
(list uid (reverse tmp))
)
((> len count)
(setq i 0)
(repeat (- len count)
(setq tmp (cons (read (strcat uid (itoa (+ count i)))) tmp)
i (1+ i)
)
)
(list uid (append (cadr ar) (reverse tmp)))
)
)
)
;; 返回数组的LISP格式数据
(defun array->list (ar /)
(mapcar 'vl-symbol-value (cadr ar))
)
演示:
_$(setq ar (array-def 3 "U"))
("U" (U0 U1 U2))
_$ (array-length ar)
3
_$ (array->list ar)
(nil nil nil)
_$(array-set ar 2 "222")
"222"
_$ (setq ar (array-set-length ar 10))
("U" (U0 U1 U2 U3 U4 U5 U6 U7 U8 U9))
_$ (array-length ar)
10
_$ (array->list ar)
(nil nil "222" nil nil nil nil nil nil nil)
_$(array-set ar 10 "222") <- 下标是从0开始的,越界的下标造成赋值失败
nil
_$(array-set ar 9 "222")
"222"
_$(array-get ar 9)
"222"
_$ (array->list ar)
(nil nil "222" nil nil nil nil nil nil "222")
_1$ (array-clear ar)
nil
_1$ (array->list ar)
(nil nil nil nil nil nil nil nil nil nil)
看到length clear set get是不是找到点VB或者C的感觉来了呢。
大家也许都明白了,所谓的数组只不过是一组符号的管理器,符号是全局的,不要和已有的变量名称冲突呐。
当然,数组的访问实际上是直接对符号的访问,速度是相当快的,适合对性能有要求的随机访问,也没有了讨厌的subst cons操作了。
lisp的优势是表,表本身就是可变的,变量放到 / 后面,函数运行结束,自动清除,(setq lst nil)就回收了,lisp虽然没有指针,但有自己特点,这样写反而失去表的灵活性了 llsheng_73数据的修改确实比subst方便,但疑惑的是如果弄一个长度为10万的数组,需要10万个变量,会不会开销太大?
测试了一个一百万长度的表,生成表就花了一分钟,时间瓶颈在read函数上。后续读写非常快的。
内存方面没有明显感觉。
这只是提供了一个思路,解决一些特殊场景下的问题,并不是不分条件地使用。 用alisper的理解就是构造 n 个全局变量,用一个表来收集符号型变量名以便清理,没必要套概念,lisp有高效简单方法 一直没有明白:数组比表的优势在哪里?可否举例说明?谢谢!
或者说数组的作用? 本帖最后由 ivde 于 2015-12-3 09:23 编辑
fl202 发表于 2015-12-3 09:15
一直没有明白:数组比表的优势在哪里?可否举例说明?谢谢!
或者说数组的作用?
数组直接开辟内存空间,用地址取值,但这不是lisp思想,用lisp就用lisp的思维方式
c++有数组,也有容器,我倒觉得vector更接近lisp思想 本帖最后由 vectra 于 2015-12-3 09:33 编辑
fl202 发表于 2015-12-3 09:15 static/image/common/back.gif
一直没有明白:数组比表的优势在哪里?可否举例说明?谢谢!
或者说数组的作用?
当你需要频繁修改表里的数据时,数组的时间复杂度是1
lisp只有一种数据结构,就是链表,访问指定位置的时间复杂度是n vectra 发表于 2015-12-3 09:31
当你需要频繁修改表里的数据时,数组的时间复杂度是1
lisp只有一种数据结构,就是链表,访问指定位置的 ...
以你的需求为例,根据需求设置变量值(set (read (setq str(strcat "aaaa" (itoa n)))) var)
(setq $gllst (cons str $gllst))
取 n 的值只需要
(vl-symbol-value (strcat "aaaa" (itoa n))即可 vectra 发表于 2015-12-3 09:31 static/image/common/back.gif
当你需要频繁修改表里的数据时,数组的时间复杂度是1
lisp只有一种数据结构,就是链表,访问指定位置的 ...
你说的时间复杂度是什么?
是指对表中的元素取值及赋值的速度吗?这个速度挺快的啊?
页:
[1]