找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3233|回复: 32

[研讨] 型参和实参相同,有什么副作用?

[复制链接]

已领礼包: 604个

财富等级: 财运亨通

发表于 2014-11-15 16:31:03 | 显示全部楼层 |阅读模式

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

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

×
;;如下面的程序,e 是相同的,执行完(MiddleCenPoint e)后再查,e没有变化,会不会有什么副作用?
;;功能:获取对象正中点
(defun MiddleCenPoint (e / P1 P2 PLIST X)
  (cond ((= (type e) 'ename) (setq e (vlax-ename->vla-object e))))
  (vla-getboundingbox e 'p1 'p2)
  (setq p1 (vlax-safearray->list p1))
  (setq p2 (vlax-safearray->list p2))
  (mapcar '(lambda (X Y) (* (+ X Y) 0.5)) P1 P2)
)
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 40个

财富等级: 招财进宝

发表于 2014-11-15 16:44:49 | 显示全部楼层
不看你的代码,从程序设计角度说

形参是通过栈传参数给函数的,传进去的是一个拷贝,你在函数内部修改形参,不会影响到外面那个变量的。
实参是通过堆传参数给函数的,传进去的是一个地址(地址的指针),你在函数内部修改实参,是会影响到外面那个变量的。

因为函数只有一个返回值,所以,如果你想返回多个值的话,你就要利用实参的特性,通过函数内部修改实参来达到返回多个值的目的。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

发表于 2014-11-15 16:53:51 | 显示全部楼层
Autolisp 规则 / 前后不能有同名的,传递的参数在函数内部任意改变值都不影响原变量,这个大概就是 N  版说的形参

点评

LISP放到函数定义 / 后面的就都是形参了。没放进去的,若果修改了和外面同名的,外面的也变了,这就相当于实参,虽然没特意传,这是LISP与众不同的地方。 其他语言变量不定义是不让用的。实参必须显示的跟着函数传  详情 回复 发表于 2014-11-15 17:05
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

发表于 2014-11-15 17:05:27 | 显示全部楼层
st788796 发表于 2014-11-15 16:53
Autolisp 规则 / 前后不能有同名的,传递的参数在函数内部任意改变值都不影响原变量,这个大概就是 N  版说 ...

LISP放到函数定义  / 后面的就都是形参了。没放进去的,若果修改了和外面同名的,外面的也变了,这就相当于实参,虽然没特意传,这是LISP与众不同的地方。 其他语言变量不定义是不让用的。实参必须显示的跟着函数传递进来才行。

点评

用Autocad自带的编辑器提取局部变量,有时也包括了e ,如(e P1 P2 PLIST X)。我就奇怪了,而且也能正常运行,只不过编译时会发出警告。  详情 回复 发表于 2014-11-17 08:30
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 604个

财富等级: 财运亨通

 楼主| 发表于 2014-11-17 08:30:15 | 显示全部楼层
本帖最后由 /db_自贡黄明儒_ 于 2014-11-17 11:38 编辑
newer 发表于 2014-11-15 17:05
LISP放到函数定义  / 后面的就都是形参了。没放进去的,若果修改了和外面同名的,外面的也变了,这就相当 ...

用Autocad自带的编辑器提取局部变量,有时也包括了e ,如(e  P1 P2 PLIST X)。我就奇怪了,而且也能正常运行,只不过编译时会发出警告。
我注意到高飞大师是如下写的
  1. (defun MiddleCenPoint (e / OBJ P1 P2 X Y)
  2.   (cond  ((= (type e) 'ename) (setq obj (vlax-ename->vla-object e)))
  3.   ((= (type e) 'VLA-OBJECT) (setq obj e))
  4.   )
  5.   (vla-getboundingbox obj 'p1 'p2)
  6.   (setq p1 (vlax-safearray->list p1))
  7.   (setq p2 (vlax-safearray->list p2))
  8.   (mapcar '(lambda (X Y) (* (+ X Y) 0.5)) P1 P2)
  9. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 6530个

财富等级: 富甲天下

发表于 2014-11-17 08:56:24 | 显示全部楼层
/db_自贡黄明儒_ 发表于 2014-11-17 08:30
用Autocad自带的编辑器提取局部变量,有时也包括了e ,如(e  P1 P2 PLIST X)。我就奇怪了,而且也能正常 ...

Acad自带的编辑器只能作参考,研究深了就自己看程序分析吧。
百度了一下,关于形参和实参还是说得比较清楚的,就是有一条,就是n版所说是Lisp的特殊性,Lisp实参可以不定义。
在ALisp的函数定义中,参数包括参数名和参数本身两个概念,参数名(及局部变量名)在函数加载时,系统会按照自己的算法分配地址,与函数外面的环境(包括系统变量、实参等)无关,所以也可以同名,并不会带来影响。
一旦定义的形参名(参数名和局部变量名)和外部环境中全局变量名相同,在函数中就只认函数中的形参名,无法再把外部环境中的实参(全局变量)传递进来,当然也无法传递出去。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 6530个

财富等级: 富甲天下

发表于 2014-11-17 09:05:23 | 显示全部楼层
/db_自贡黄明儒_ 发表于 2014-11-17 08:30
用Autocad自带的编辑器提取局部变量,有时也包括了e ,如(e  P1 P2 PLIST X)。我就奇怪了,而且也能正常 ...

鸟大师这段代码的变量声明中x、y多余。
这里的e是参数名,可以是任意字符,并不改变函数的内容,如果在加载之前已经设定e为另一个值,则在此函数运行时将无法改变前面设定的e值,obj、pt1等也一样。
这种问题一般不影响使用,除非你又想调用此函数,又想改变函数外的同名函数。

点评

x、y是我用自带的编辑器提取的  发表于 2014-11-17 10:56
我是说高飞大师这样写 [*](cond ((= (type e) 'ename) (setq obj (vlax-ename->vla-object e))) [*] ((= (type e) 'VLA-OBJECT) (setq obj e)) [*] ) 而不是 [*](cond ((= (type e) 'ename) (s  详情 回复 发表于 2014-11-17 10:55
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 604个

财富等级: 财运亨通

 楼主| 发表于 2014-11-17 10:55:19 | 显示全部楼层
ll_j 发表于 2014-11-17 09:05
鸟大师这段代码的变量声明中x、y多余。
这里的e是参数名,可以是任意字符,并不改变函数的内容,如果在 ...

我是说高飞大师这样写
  • (cond  ((= (type e) 'ename) (setq obj (vlax-ename->vla-object e)))

  •                                
    登录/注册后可看大图
      ((= (type e) 'VLA-OBJECT) (setq obj e))

  •                                
    登录/注册后可看大图
      )



    而不是
  • (cond  ((= (type e) 'ename) (setq e (vlax-ename->vla-object e))))这样写


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

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

发表于 2014-11-17 11:22:51 | 显示全部楼层
/db_自贡黄明儒_ 发表于 2014-11-17 10:55
我是说高飞大师这样写
  • (cond  ((= (type e) 'ename) (setq obj (vlax-ename->vla-object e)))

  • 自己函数内部再写一个变量,习惯,按 2  写也没问题

    点评

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

    使用道具 举报

    已领礼包: 6530个

    财富等级: 富甲天下

    发表于 2014-11-17 11:29:40 | 显示全部楼层
    /db_自贡黄明儒_ 发表于 2014-11-17 10:55
    我是说高飞大师这样写
  • (cond  ((= (type e) 'ename) (setq obj (vlax-ename->vla-object e)))

  • 仔细看,好像鸟兄的代码有错误,下面的一句vla-getb...中的参数e应该是obj。
    不懂vl,所以去查了一下书,这个函数参数似乎应该是object对象,而且看鸟兄的代码页应该是这样,前面的cond是对e进行判别,e是实体就转换为对象,赋值到obj,是对象直接赋值到obj,当然,这里可以省略obj变量,直接就使用e,但编程有习惯的约定俗成,e、en、ent表示实体,obj表示对象,所以不妨多一个变量名。
    11111.jpg

    点评

    趁高飞大师可能还没有看到,我改了,免得说我乱打他的旗号。其实我只想说一个问题,不严密导致其它问题了。  详情 回复 发表于 2014-11-17 11:49
    那不是高飞大师的错,是我写错了。 我只是想说明前面那个问题  详情 回复 发表于 2014-11-17 11:40
    论坛插件加载方法
    发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
    如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
    如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
    回复 支持 反对

    使用道具 举报

    已领礼包: 604个

    财富等级: 财运亨通

     楼主| 发表于 2014-11-17 11:40:12 | 显示全部楼层
    本帖最后由 /db_自贡黄明儒_ 于 2014-11-17 11:41 编辑
    ll_j 发表于 2014-11-17 11:29
    仔细看,好像鸟兄的代码有错误,下面的一句vla-getb...中的参数e应该是obj。
    不懂vl,所以去查了一下书 ...

    那不是高飞大师的错,是我写错了。{:soso_e127:}
    我只是想说明前面8楼那个问题

    点评

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

    使用道具 举报

    已领礼包: 1268个

    财富等级: 财源广进

    发表于 2014-11-17 11:47:36 | 显示全部楼层
    还没有上升到理论高度,在 AutoLISP 自定义函数中内部函数名称一直不使用参数名的,需要转换就另起个名字
    论坛插件加载方法
    发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
    如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
    如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
    回复 支持 反对

    使用道具 举报

    已领礼包: 604个

    财富等级: 财运亨通

     楼主| 发表于 2014-11-17 11:49:55 | 显示全部楼层
    ll_j 发表于 2014-11-17 11:29
    仔细看,好像鸟兄的代码有错误,下面的一句vla-getb...中的参数e应该是obj。
    不懂vl,所以去查了一下书 ...

    趁高飞大师可能还没有看到,我改了,免得说我乱打他的旗号{:soso_e113:}。其实我只想说一个问题,不严密导致其它问题了。

    点评

    在 C++ .Net 中参数有 ref 类型,可以输出变量,AutoLISP 一般用 setq 也可以留下全局变量,但是在不同的编译空间,这个setq 就不够了,Autodesk 为此体高了几个函数,vl-bb-ref vl-bb-set vl-doc-import vl-doc-  详情 回复 发表于 2014-11-17 11:58
    论坛插件加载方法
    发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
    如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
    如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
    回复 支持 反对

    使用道具 举报

    发表于 2014-11-17 11:58:15 | 显示全部楼层
    /db_自贡黄明儒_ 发表于 2014-11-17 11:49
    趁高飞大师可能还没有看到,我改了,免得说我乱打他的旗号。其实我只想说一个问题,不严密 ...

    在 C++ .Net  中参数有 ref 类型,可以输出变量,AutoLISP 一般用  setq 也可以留下全局变量,但是在不同的编译空间,这个setq 就不够了,Autodesk 为此体高了几个函数,vl-bb-ref vl-bb-set vl-doc-import vl-doc-export vl-propagete ,另外还可以想下面这样用
    1. (defun fy:ODBX (varSym fn)
    2.   (if (set varSym
    3.        (vla-GetInterfaceObject
    4.          (vlax-get-acad-object)
    5.          (strcat "ObjectDBX.AxDbDocument."
    6.              (substr (getvar "acadver") 1 2)
    7.          )
    8.        )
    9.       )
    10.     (if    (and fn (findfile fn))
    11.       (vla-open (eval varsym) (findfile fn))
    12.       (eval varsym)
    13.     )
    14.   )
    15. )

    使用方法如下

    (fy:odbx 'dbxdoc "test.dwg")
    (if dbxdoc
       (vlax-for x (vla-get-modelspace dbxdoc)
      ....



    点评

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

    使用道具 举报

    已领礼包: 604个

    财富等级: 财运亨通

     楼主| 发表于 2014-11-17 12:09:27 | 显示全部楼层
    Free-Lancer 发表于 2014-11-17 11:58
    在 C++ .Net  中参数有 ref 类型,可以输出变量,AutoLISP 一般用  setq 也可以留下全局变量,但是在不 ...

    set函数历来是个难点,看来你驾轻就熟

    点评

    在 AutoLISP 中,变量名和值是统一的,这个 指针、地址概念不同,自定义函数中参数传递的是 “值”,对应其它语言的 “地址”,看看下面的例子 _$ (setq l1 '(1 2 3 4)) (1 2 3 4) _$ (setq l2 '(a b c d)) (  详情 回复 发表于 2014-11-17 13:45
    论坛插件加载方法
    发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
    如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
    如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-11-15 05:16 , Processed in 0.269923 second(s), 59 queries , Gzip On.

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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