找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 9429|回复: 41

[已解决] 哪位大大来解释下这个函数为什么是这样的写法?

[复制链接]
发表于 2013-8-1 22:15:58 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 wowan1314 于 2013-8-2 11:39 编辑

  1. (defun LM:acdoc nil
  2.   (eval (list 'defun
  3.        'LM:acdoc
  4.        'nil
  5.        (vla-get-activedocument (vlax-get-acad-object))
  6. )
  7.   )
  8.   (LM:acdoc)
  9. )


这样写的好处是:第一次调用时,函数会执行(vla-get-activedocument (vlax-get-acad-object))这句代码。


但是以后再执行这个函数,就不会再执行(vla-get-activedocument (vlax-get-acad-object))这个代码.而直接返回 其代表的值。相当于设置一个全局变量一样。

不知道为什么会这么神奇?  这个代码是怎么运行的? 下次调用怎么会直接返回值而不再去执行相应的代码?

本帖被以下淘专辑推荐:

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
 楼主| 发表于 2013-8-16 12:05:48 | 显示全部楼层
我谈下我的理解,因为我想的比较简单。也许不正确。
1、这个函数第一次运行后,以后再运行就是执行 EVAL 里面重新定义的函数了
    这一点大家都知道了。
2、那么关键就是EVAL里的重新定义。这个list  里面共四个元素。前三个有'号。最后一个没有。
    所以最后一句在第一次执行时候是被运行了的。

重新定义后的函数其实是这样的!
  1. (defun LM:acdoc nil
  2.    #<VLA-OBJECT IAcadDocument 0114d320>
  3. )
里面已经没有代码了。只有值了。

点评

这个理解 是正确的,因为list不加eval 只是代表一个列表,加上后相当于对函数重定义一个定值函数, 这个函数应用 个人理解应该用为每个程序的局部变量使用  详情 回复 发表于 2013-12-5 13:31

评分

参与人数 1D豆 +5 收起 理由
bzhjl + 5 很给力!经验;技术要点;资料分享奖!

查看全部评分

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

使用道具 举报

 楼主| 发表于 2013-8-1 22:19:56 | 显示全部楼层
  1. ;; Multiple Nested Copy  -  Lee Mac
  2. ;; Copies all components of a selected block reference to the active space.

  3. (defun c:ncopym ( / ent lst mat obj )
  4.     (while
  5.         (progn (setvar 'errno 0) (setq ent (car (entsel "\nSelect Block Reference: ")))
  6.             (cond
  7.                 (   (= 7 (getvar 'errno))
  8.                     (princ "\nMissed, try again.")
  9.                 )
  10.                 (   (= 'ename (type ent))
  11.                     (setq obj (vlax-ename->vla-object ent))
  12.                     (cond
  13.                         (   (/= "AcDbBlockReference" (vla-get-objectname obj))
  14.                             (princ "\nSelected object is not a block reference.")
  15.                         )
  16.                         (   (= :vlax-true (vla-get-hasattributes obj))
  17.                             (princ "\nSelected block must not be attributed.")
  18.                         )
  19.                         (   (= :vlax-true (vla-get-isdynamicblock obj))
  20.                             (princ "\nSelected block must not be dynamic.")
  21.                         )
  22.                         (   (not
  23.                                 (and
  24.                                     (equal (vla-get-xscalefactor obj) (vla-get-yscalefactor obj) 1e-8)
  25.                                     (equal (vla-get-xscalefactor obj) (vla-get-zscalefactor obj) 1e-8)
  26.                                 )
  27.                             )
  28.                             (princ "\nSelected block must be uniformly scaled.")
  29.                         )                                    
  30.                         (   t
  31.                             (setq mat
  32.                                 (vlax-tmatrix
  33.                                     (apply
  34.                                         (function
  35.                                             (lambda ( mat vec )
  36.                                                 (append (mapcar 'append mat (mapcar 'list vec))
  37.                                                    '((0.0 0.0 0.0 1.0))
  38.                                                 )
  39.                                             )
  40.                                         )
  41.                                         (refgeom ent)
  42.                                     )
  43.                                 )
  44.                             )
  45.                             (vlax-for obj (vla-item (vla-get-blocks (LM:acdoc)) (vla-get-name obj))
  46.                                 (setq lst (cons obj lst))
  47.                             )
  48.                             (foreach obj
  49.                                 (vlax-invoke (LM:acdoc) 'copyobjects (reverse lst)
  50.                                     (vlax-ename->vla-object (cdr (assoc 330 (entget ent))))
  51.                                 )
  52.                                 (vla-transformby obj mat)
  53.                             )
  54.                         )
  55.                     )
  56.                 )
  57.             )
  58.         )
  59.     )
  60.     (princ)
  61. )

  62. ;; RefGeom (gile)
  63. ;; Returns a list whose first item is a 3x3 transformation matrix and
  64. ;; second item the object insertion point in its parent (xref, block or space)

  65. (defun refgeom ( ent / ang enx mat ocs )
  66.     (setq enx (entget ent)
  67.           ang (cdr (assoc 050 enx))
  68.           ocs (cdr (assoc 210 enx))
  69.     )
  70.     (list
  71.         (setq mat
  72.             (mxm
  73.                 (mapcar '(lambda ( v ) (trans v 0 ocs t))
  74.                    '(
  75.                         (1.0 0.0 0.0)
  76.                         (0.0 1.0 0.0)
  77.                         (0.0 0.0 1.0)
  78.                     )
  79.                 )
  80.                 (mxm
  81.                     (list
  82.                         (list (cos ang) (- (sin ang)) 0.0)
  83.                         (list (sin ang) (cos ang)     0.0)
  84.                        '(0.0 0.0 1.0)
  85.                     )
  86.                     (list
  87.                         (list (cdr (assoc 41 enx)) 0.0 0.0)
  88.                         (list 0.0 (cdr (assoc 42 enx)) 0.0)
  89.                         (list 0.0 0.0 (cdr (assoc 43 enx)))
  90.                     )
  91.                 )
  92.             )
  93.         )
  94.         (mapcar '- (trans (cdr (assoc 10 enx)) ocs 0)
  95.             (mxv mat (cdr (assoc 10 (tblsearch "block" (cdr (assoc 2 enx))))))
  96.         )
  97.     )
  98. )

  99. ;; Matrix Transpose  -  Doug Wilson
  100. ;; Args: m - nxn matrix

  101. (defun trp ( m )
  102.     (apply 'mapcar (cons 'list m))
  103. )

  104. ;; Matrix x Matrix  -  Vladimir Nesterovsky
  105. ;; Args: m,n - nxn matrices

  106. (defun mxm ( m n )
  107.     ((lambda ( a ) (mapcar '(lambda ( r ) (mxv a r)) m)) (trp n))
  108. )

  109. ;; Matrix x Vector  -  Vladimir Nesterovsky
  110. ;; Args: m - nxn matrix, v - vector in R^n

  111. (defun mxv ( m v )
  112.     (mapcar '(lambda ( r ) (apply '+ (mapcar '* r v))) m)
  113. )

  114. ;; Active Document  -  Lee Mac
  115. ;; Returns the VLA Active Document Object

  116. (defun LM:acdoc nil
  117.     (eval (list 'defun 'LM:acdoc 'nil (vla-get-activedocument (vlax-get-acad-object))))
  118.     (LM:acdoc)
  119. )

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

使用道具 举报

 楼主| 发表于 2013-8-1 22:20:49 | 显示全部楼层
本帖最后由 wowan1314 于 2013-8-2 11:09 编辑

汉字是多么亲切的一种语言啊。。 怎么那么地方用英语?!


The use of defun-q will help to explain the difference:

Consider the following functions:
  1. (defun-q f1 nil
  2.     (vla-get-activedocument (vlax-get-acad-object))
  3. )
  1. (defun-q f2 nil
  2.     (eval (list 'defun-q 'f2 'nil (vla-get-activedocument (vlax-get-acad-object))))
  3.     (f2)
  4. )
Before function evaluation, the respective function definitions are as follows:
  1. _$ f1
  2. (nil (vla-get-ActiveDocument (vlax-get-acad-object)))
  3. _$ f2
  4. (nil (EVAL (LIST (QUOTE DEFUN-Q) (QUOTE F2) (QUOTE nil) (vla-get-ActiveDocument (vlax-get-acad-object)))) (F2))
复制代码
When evaluated, both functions will return the Active Document object:
  1. _$ (f1)
  2. #<VLA-OBJECT IAcadDocument 0ceb5b6c>
  3. _$ (f2)
  4. #<VLA-OBJECT IAcadDocument 0ceb5b6c>
复制代码
However, observe the respective function definitions following function evaluation:
  1. _$ f1
  2. (nil (vla-get-ActiveDocument (vlax-get-acad-object)))
  3. _$ f2
  4. (nil #<VLA-OBJECT IAcadDocument 0ceb5b6c>)
复制代码
Note that function f2 now no longer retrieves the Application Object (vlax-get-acad-object) before retrieving the Active Document Property (vla-get-activedocument), but simply returns the Active Document object directly. The method is similar to setting a global variable pointing to the Active Document Object.

Of course, for this program, I could have equivalently used a local variable assigned with the Active Document Object, however, such local variable would then be re-assigned this value for every use of the program.
&#171; Last Edit: June 04, 2013, 07:53:20 am by Lee Mac &#187;
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

发表于 2013-8-2 08:05:34 | 显示全部楼层
一楼的帖子,对里面的符号用EVAL求值,就把函数DEFUN了。

点评

我是问这个函数为什么这样写?? 这样写有什么好处? 为什么会有这种好处?  详情 回复 发表于 2013-8-2 10:29
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-2 10:29:11 | 显示全部楼层
newer 发表于 2013-8-2 08:05
一楼的帖子,对里面的符号用EVAL求值,就把函数DEFUN了。

我是问这个函数为什么这样写??  
这样写有什么好处?
为什么会有这种好处?

点评

你这么说,我才又看了次程序,外面定义的名字 和里面 EVAL定义的一样,我看到他在函数里面又递归调用了自己。我们知道LISP求值是从最内部的括号求完再到外面的括号,看作者的代码,是想在里面执行函数的时候要保证这  详情 回复 发表于 2013-8-2 10:48
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

发表于 2013-8-2 10:48:39 | 显示全部楼层
wowan1314 发表于 2013-8-2 10:29
我是问这个函数为什么这样写??  
这样写有什么好处?
为什么会有这种好处?

你这么说,我才又看了次程序,外面定义的名字 和里面 EVAL定义的一样,我看到他在函数里面又递归调用了自己。我们知道LISP求值是从最内部的括号求完再到外面的括号,看作者的代码,是想在里面执行函数的时候要保证这个函数安全的定义了(通过上面的EVAL,注意EVAL里面的同名函数并没递归调用的语句,作者是想通过这样的写法,在函数第一个执行的时候不递归调用,第二次后才开始递归)。

我不知道我上面说的是不是作者的想法,毕竟他选择这样写的,我也不知道我上面说的,你是不是能明白我要表达的意思。

点评

这没有用递归吧,应该不算递归,里面的定义覆盖了原函数。有什么好处就不清楚了。  详情 回复 发表于 2013-8-2 11:11
你的意思我没明白。3楼是LEE-MAC原作者的解释。 英语汉语我都没明白。  发表于 2013-8-2 11:07
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 3884个

财富等级: 富可敌国

发表于 2013-8-2 11:11:15 | 显示全部楼层
newer 发表于 2013-8-2 10:48
你这么说,我才又看了次程序,外面定义的名字 和里面 EVAL定义的一样,我看到他在函数里面又递归调用了自 ...

这没有用递归吧,应该不算递归,里面的定义覆盖了原函数。有什么好处就不清楚了。

点评

好处是:第一次调用时,函数会执行(vla-get-activedocument (vlax-get-acad-object))这句代码。 但是以后再执行这个函数,就不会再调用(vla-get-activedocument (vlax-get-acad-object))这个代码而直接返回 其  详情 回复 发表于 2013-8-2 11:17

评分

参与人数 1D豆 +5 收起 理由
wowan1314 + 5 感觉覆盖是正确的说法。

查看全部评分

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

使用道具 举报

 楼主| 发表于 2013-8-2 11:17:32 | 显示全部楼层
本帖最后由 wowan1314 于 2013-8-2 11:26 编辑
ayl1004 发表于 2013-8-2 11:11
这没有用递归吧,应该不算递归,里面的定义覆盖了原函数。有什么好处就不清楚了。

好处是:第一次调用时,函数会执行(vla-get-activedocument (vlax-get-acad-object))这句代码。


但是以后再执行这个函数,就不会再执行(vla-get-activedocument (vlax-get-acad-object))这个代码.而直接返回 其代表的值。相当于设置一个全局变量一样。


不知道为什么会这么神奇?  这个代码是怎么运行的? 下次调用怎么会直接返回值而不再去执行相应的代码?

点评

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

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

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

使用道具 举报

已领礼包: 604个

财富等级: 财运亨通

发表于 2013-8-15 09:10:38 | 显示全部楼层
确实很奇怪,搞不明白,帮你顶一下{:soso_e181:}。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

发表于 2013-8-15 09:12:43 | 显示全部楼层
wowan1314 发表于 2013-8-2 11:17
好处是:第一次调用时,函数会执行(vla-get-activedocument (vlax-get-acad-object))这句代码。

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

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

发表于 2013-8-15 09:22:18 | 显示全部楼层
nil <=> ()
这个 nil 有时让人迷惑
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2013-8-15 20:03:59 | 显示全部楼层
Lisp里面"符号"既可以储存变量也可以储存函数
也可以说不仅defun用来定义函数,setq 也可以
这个程序第一次执行完eval函数后再执行(f2)等于是(setq f2 (vla...))
好处就是,这是一个coding理念:尽量减少全局变量的使用。coders相信在五千行以上规模的程序中,全局变量绝对是灾难之源。
我相信能参与到这种代码规模的人一定不少,但是更多人写的程序不会超过200行。

点评

能举一些全局变量时灾难之源的例子吗?  详情 回复 发表于 2013-8-15 20:15
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

发表于 2013-8-15 20:15:41 | 显示全部楼层
MoremoreGold 发表于 2013-8-15 20:03
Lisp里面"符号"既可以储存变量也可以储存函数
也可以说不仅defun用来定义函数,setq 也可以
这个程序第一 ...

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

使用道具 举报

发表于 2013-8-15 20:23:38 | 显示全部楼层
我不是coders,我写的小东西100行都嫌多
减少全局变量的使用是程序员的理念

点评

我认为全局变量肯定不能取消,不管多少,主要是要有一个妥善的管理方法。否则再少的全局变量也会造成冲突,反而管理得当,再多的也相安无事。  详情 回复 发表于 2013-8-15 20:38
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-21 21:09 , Processed in 0.471384 second(s), 62 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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