明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 2566|回复: 8

[源码] 打造随机访问的LISP可变长数组

[复制链接]
发表于 2015-12-2 20:52:16 | 显示全部楼层 |阅读模式
本帖最后由 vectra 于 2015-12-2 20:58 编辑

LISP语言没有指针和引用,有时实在是不太方便,请看这个LISP可变长数组

  1. ;; 定义一个可以容纳len个数据的数组
  2. (defun array-def (len uid / ar i)
  3.   (setq i 0)
  4.   (repeat len
  5.     (setq ar (cons (read (strcat uid (itoa i))) ar)
  6.           i  (1+ i)
  7.     )
  8.   )
  9.   (list uid (reverse ar))
  10. )
  11. ;; 销毁数组对象并释放内存
  12. (defun array-clear (ar /)
  13.   (foreach e (cadr ar)
  14.     (set e nil)
  15.   )
  16. )
  17. ;; 为数组指定索引位置赋值,成功返回值,失败返回nil
  18. (defun array-set (ar i val / uid)
  19.   (setq uid (car ar))
  20.   (if (and (>= i 0) (< i (length (cadr ar))))
  21.     (set (read (strcat uid (itoa i))) val)
  22.   )
  23. )
  24. ;; 获取数组指定索引位置值
  25. (defun array-get (ar i / uid)
  26.   (setq uid (car ar))
  27.   (if (and (>= i 0) (< i (length (cadr ar))))
  28.     (vl-symbol-value (read (strcat uid (itoa i))))
  29.   )
  30. )
  31. ;; 返回数组的容量
  32. (defun array-length (ar /)
  33.   (length (cadr ar))
  34. )
  35. ;; 重新设置数组的容量
  36. (defun array-set-length        (ar len / count uid i tmp)
  37.   (setq        uid   (car ar)
  38.         count (array-length ar)
  39.   )
  40.   (cond
  41.     ((< len count)
  42.      (setq ar (cadr ar))
  43.      (repeat len
  44.        (setq tmp (cons (car ar) tmp)
  45.              ar         (cdr ar)
  46.        )
  47.      )
  48.      (foreach e        ar
  49.        (set e nil)
  50.      )
  51.      (list uid (reverse tmp))
  52.     )

  53.     ((> len count)
  54.      (setq i 0)
  55.      (repeat (- len count)
  56.        (setq tmp (cons (read (strcat uid (itoa (+ count i)))) tmp)
  57.              i         (1+ i)
  58.        )
  59.      )
  60.      (list uid (append (cadr ar) (reverse tmp)))
  61.     )
  62.   )
  63. )
  64. ;; 返回数组的LISP格式数据
  65. (defun array->list (ar /)
  66.   (mapcar 'vl-symbol-value (cadr ar))
  67. )


演示:
_$  (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操作了。



点评

数据的修改确实比subst方便,但疑惑的是如果弄一个长度为10万的数组,需要10万个变量,会不会开销太大?  发表于 2015-12-2 23:46

评分

参与人数 1明经币 +1 收起 理由
lucas_3333 + 1 赞一个!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下

本帖被以下淘专辑推荐:

  • · 学习|主题: 95, 订阅: 8
发表于 2015-12-2 23:45:51 来自手机 | 显示全部楼层
lisp的优势是表,表本身就是可变的,变量放到 / 后面,函数运行结束,自动清除,(setq lst nil)就回收了,lisp虽然没有指针,但有自己特点,这样写反而失去表的灵活性了
 楼主| 发表于 2015-12-3 08:29:41 | 显示全部楼层
llsheng_73  数据的修改确实比subst方便,但疑惑的是如果弄一个长度为10万的数组,需要10万个变量,会不会开销太大?


测试了一个一百万长度的表,生成表就花了一分钟,时间瓶颈在read函数上。后续读写非常快的。

内存方面没有明显感觉。

这只是提供了一个思路,解决一些特殊场景下的问题,并不是不分条件地使用。
发表于 2015-12-3 09:02:09 来自手机 | 显示全部楼层
用alisper的理解就是构造 n 个全局变量,用一个表来收集符号型变量名以便清理,没必要套概念,lisp有高效简单方法
发表于 2015-12-3 09:15:16 | 显示全部楼层
一直没有明白:数组比表的优势在哪里?可否举例说明?谢谢!

或者说数组的作用?
发表于 2015-12-3 09:20:46 来自手机 | 显示全部楼层
本帖最后由 ivde 于 2015-12-3 09:23 编辑
fl202 发表于 2015-12-3 09:15
一直没有明白:数组比表的优势在哪里?可否举例说明?谢谢!

或者说数组的作用?


数组直接开辟内存空间,用地址取值,但这不是lisp思想,用lisp就用lisp的思维方式

c++有数组,也有容器,我倒觉得vector更接近lisp思想
 楼主| 发表于 2015-12-3 09:31:17 | 显示全部楼层
本帖最后由 vectra 于 2015-12-3 09:33 编辑
fl202 发表于 2015-12-3 09:15
一直没有明白:数组比表的优势在哪里?可否举例说明?谢谢!

或者说数组的作用?

当你需要频繁修改表里的数据时,数组的时间复杂度是1

lisp只有一种数据结构,就是链表,访问指定位置的时间复杂度是n
发表于 2015-12-3 09:40:04 来自手机 | 显示全部楼层
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))即可
发表于 2015-12-4 09:11:10 | 显示全部楼层
vectra 发表于 2015-12-3 09:31
当你需要频繁修改表里的数据时,数组的时间复杂度是1

lisp只有一种数据结构,就是链表,访问指定位置的 ...

你说的时间复杂度是什么?
是指对表中的元素取值及赋值的速度吗?这个速度挺快的啊?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-12-27 09:32 , Processed in 0.180304 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表