找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3459|回复: 1

[研讨] Alisp 中实现函数参数的修改

[复制链接]

已领礼包: 1268个

财富等级: 财源广进

发表于 2016-6-16 09:03:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一般来说 Autolisp 的参数是形参

  1. (setq a 10.0)
  2. (defun ff (a / ) (setq a 1.0))
  3. (setq b (ff a))

函数体内对 a 进行了赋值,外部的 a 仍旧是 10.0 ,不会变成 1.0,ff 的返回值是 1.0,ff 中的 a 是一个值参数;
在 c++ 中传递指针或地址做参数后,如果函数体内对指针或地址的值进行修改,外部的指针或地址指向的值也会修改;
C# 中如果参数是集合,那么函数体内对集合进行了修改,那么传递的该参数指向也会变化,除了函数体可以返回指定的类型,还可以有一个 ref 修饰的参数用于修改外部变量

现在的问题是 Autolisp 是不是也具有以上类似的特性呢,传递的参数也可以在函数体内进行修改?答案是肯定的,不过要使用一个特殊的类型,即 SafeArray, 看下面的例子


  1. (setq arr (vlax-safearray-fill (vlax-make-safearray vlax-vbdouble '(0 . 0)) '(10.0)))
  2. (defun ff (a) (vlax-safearray-put-element a 0 1.0) 1.0)
  3. (vlax-safearray->list a)

运行后的效果
_$ (vlax-safearray->list arr)
(10.0)
_$ (ff arr)
1.0
_$ (vlax-safearray->list arr)
(1.0)

当然这种方法有些绕,不过在某些情况下使用会更加方便,一个实例
这是一个 C++ 的最小二乘法模拟椭圆程序 http://blog.csdn.net/zhazhiqiang/article/details/45824957
下面用 SafeArray 参数改写第一个函数 高斯消元

  1. (defun RGauss (arr / n m narr k dmax i j k temp x)
  2.   (setq        n    (vlax-safearray-get-u-bound arr 1)
  3.         m    (vlax-safearray-get-u-bound arr 2)
  4.         narr arr
  5.         k    0
  6.   )
  7.   (while (< k n)
  8.     (setq dmax -1
  9.           l -1
  10.           i k
  11.     )
  12.     (while (< i n)
  13.       (if (> (abs (vlax-safearray-get-element narr i k)) dmax)
  14.         (setq dmax (vlax-safearray-get-element narr i k)
  15.               l           i
  16.         )
  17.       )
  18.       (setq i (1+ i))
  19.     )
  20.     (if        (/= l k)
  21.       (progn
  22.         (setq i 0)
  23.         (while (< i m)
  24.           (setq temp (vlax-safearray-get-element narr l i))
  25.           (vlax-safearray-put-element narr l i (vlax-safearray-get-element narr k i))
  26.           (vlax-safearray-put-element narr k i temp)
  27.           (setq i (1+ i))
  28.         )
  29.       )
  30.     )
  31.     (setq i (1+ k))
  32.     (while (< i n)
  33.       (setq l (/ (vlax-safearray-get-element narr i k) (vlax-safearray-get-element narr k k)))
  34.       (setq j k)
  35.       (while (< j m)
  36.         (vlax-safearray-put-element
  37.           narr
  38.           i
  39.           j
  40.           (- (vlax-safearray-get-element narr i j) (* l (vlax-safearray-get-element narr k j)))
  41.         )
  42.         (setq j (1+ j))
  43.       )
  44.       (setq i (1+ i))
  45.     )
  46.     (setq k (1+ k))
  47.   )
  48.   (setq x (vlax-make-safearray vlax-vbdouble (cons 0 (1- n))))
  49.   (vlax-safearray-put-element
  50.     x
  51.     (1- n)
  52.     (/ (vlax-safearray-get-element narr (1- n) (1- m)) (vlax-safearray-get-element narr (1- n) (- m 2)))
  53.   )
  54.   (setq k (- n 2))
  55.   (while (>= k 0)
  56.     (setq s 0.0
  57.           j (1+ k)
  58.     )
  59.     (while (< j n)
  60.       (setq s (+ s (* (vlax-safearray-get-element narr k j) (vlax-safearray-get-element x j)))
  61.             j (1+ j)
  62.       )
  63.     )
  64.     (vlax-safearray-put-element
  65.       x
  66.       k
  67.       (/ (- (vlax-safearray-get-element narr k (1- m)) s) (vlax-safearray-get-element narr k k))
  68.     )
  69.     (setq k (1- k))
  70.   )
  71.   x
  72. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 8121个

财富等级: 富甲天下

发表于 2016-6-22 23:24:16 | 显示全部楼层
本帖最后由 Highflybird 于 2016-6-22 23:27 编辑

关于这个问题,其实不用安全数组也是可以的,
譬如简单的交换函数:
  1. (defun SWAP (SwapX SwapY / temp)
  2.   (setq temp (VL-SYMBOL-VALUE SwapX))
  3.   (set SwapX (VL-SYMBOL-VALUE SwapY))
  4.   (set SwapY temp)
  5. )


运行 (setq x 1 y 2)
=>  (swap 'x 'y)
通过交换函数之后:
=> x
2
=> y
1
可以看出x和y的值真的交换了。
比较下面的函数:
(defun swap1 (x y / temp)
  (setq temp x x y y temp)
)
读者自行实验。
这个地方的技巧在于: 用quote,即 ' Set
这样LISP就可以实现修改参数值,达到传值的效果。

评分

参与人数 1D豆 +10 收起 理由
/db_自贡黄明儒_ + 10 很给力!经验;技术要点;资料分享奖!

查看全部评分

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-5-22 08:37 , Processed in 0.284579 second(s), 33 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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