明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
楼主: highflybird

[【高飞鸟】] LISP陷阱与缺陷

    [复制链接]
发表于 2022-9-12 08:40:21 | 显示全部楼层
谢谢大佬的分享!!!!
发表于 2022-9-12 09:24:16 | 显示全部楼层
本帖最后由 guosheyang 于 2022-9-12 10:06 编辑

(defun test (lst / x)
  (setq  x 1)
  (foreach x  lst (setq x 2))  
  x

(test '(1 2 3)) =>1     
      这个代码中的foreach部分,实际上是个子函数,这个子函数返回的最后值是2, 到主函数中并没有将其赋给x变量,而子函数中的x是局部变量,这也是通行的做法, 所以主函数中的值并没有被改变,这个是比较好理解的,如果改为mapcar、vl-remove-if等结合lambda临时函数也是一样的效果
  (defun test (lst / x)
  (setq  x 1)
  (mapcar'(lambda(x)(setq x 2))lst)
  x
)



(defun test (lst / x)
  (setq  x 1)      
  (vl-remove-if-not'(lambda(x)(and(= x 2)(setq x 2)))lst)
  x
)

发表于 2022-9-13 10:21:44 | 显示全部楼层
虽然我看不懂,但是觉得高飞鸟是一个很认真的人
发表于 2022-9-13 15:48:51 | 显示全部楼层
本帖最后由 guosheyang 于 2022-9-13 17:18 编辑

关于a b值对换的那个函数个人认为,这样写也是可以的, 给函数传入的是 '(3  4) 返回的是'(4 3)  让函数有个返回值(函数执行还是要通过返回值来体现结果)这样也算是达到目的了
(setq a 3 b 4)
(defun swap (x y / temp)
  (setq temp x x y y temp)
  (list x y)
)
(swap a b)   
用函数返回结果来表达 (setq x 3 y 4)  (swap x y) 的返回值也是交换了的,当然如果要让x y变量的值改变,即!x  !y的值也改变,必须重新赋值
(setq fhz(swap x y))  (setq x(car fhz))  (setq y(cadr fhz))
如果不用函数来实现,也可以直接用赋值语句也可以实现目的  (setq a 3 b 4)  (setq temp a a b b temp)



发表于 2022-9-13 16:16:41 | 显示全部楼层
lisp最大的缺陷是与主流语言区别较大,使用人群交少。
发表于 2022-9-13 17:06:45 | 显示全部楼层
原文中 这句  (setq x  1) (defun test (x)   (setq x 2))
                   然后(test x) =>2  , 检查x的值,_$ x =>1
               
   这里的值没有变化,是因为没有将返回值2赋给x ,因为函数中的x是局部变量,加上赋值语句(setq x(test x)) 才能改变x的值。通过子函数得到的返回结果一样都需要重新赋值,有时候返回值是一个列表的情况,还需要(setq a(car fhz)) (setq b(cadr fhz)) (setq c(caddr fhz)) 等来处理。   .回复了几个我的看法,希望没有冒犯到高大师哈,我只是表达我的一点看法而已

点评

理解很正确!  发表于 2022-9-14 10:51
发表于 2022-9-16 07:57:46 | 显示全部楼层
高版主讲解的非常透彻,谢谢大师指导
发表于 2022-9-16 17:09:48 | 显示全部楼层
高大师,研究严谨.学习!
发表于 2022-10-17 09:46:16 | 显示全部楼层
llsheng_73 发表于 2022-9-11 17:49
这一篇把lisp的陷阱讲得很透彻,认真研读理解后可以避免踩很多不必要的雷。

此外曾碰到过两类陷阱:

“二、传址的陷阱”这部分没太看懂,实参、形参是什么意思,楼主能否再讲明白一些呢?
发表于 2022-10-17 18:23:02 | 显示全部楼层
yjtdkj 发表于 2022-10-17 09:46
“二、传址的陷阱”这部分没太看懂,实参、形参是什么意思,楼主能否再讲明白一些呢?

函数定义过程列出的参数均为形参(形式意义上的参数,没有值)
在调用有参函数时所用的的参数为“实际参数”。它包含了实实在在的数据,会被函数内部的代码使用。与形参一一对应,否则会发生错误
一般情况下,实参传递值给形参,在被调用的函数内部不管对形参怎么修改,实参不会改变
但特殊情况下,修改形参会导致实参被修改,如果实参不是以值的形式传递给形参而是以地址方式传递的话,比如
(vla-GetBoundingBox obj 'a 'b)会修改a和b,这里参数传递方式是明确了按地址传递的,此处没有陷阱。
另ssdel和ssadd会对实参进行修改,但传递参数的时候并没有向上边一样明确指定按址传递(ssdel e ss)(ssadd e ss)都会把返回值修改到ss变量,此处可以认为是有益的陷阱,因为可以省去一个setq而达到修改变量为函数返回值的目的
一般说传址的陷阱是指,传参过程并没有明确哪个参数需要按址传递,但函数返回值的同时,会对某些实参进行修改,修改的结果还不一定是所调用的函数的返回值,可能只是那个函数执行过程的一些过程数据,所以对于不太熟悉的函数需要多测试它,才可能发现它的问题,使用过程中避免它

评分

参与人数 2明经币 +1 金钱 +30 收起 理由
yjtdkj + 1 很给力!
highflybird + 30 赞一个!

查看全部评分

回复 支持 2 反对 0

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-25 10:06 , Processed in 0.186875 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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