spp_wall 发表于 2022-9-12 08:40:21

谢谢大佬的分享!!!!

guosheyang 发表于 2022-9-12 09:24:16

本帖最后由 guosheyang 于 2022-9-12 10:06 编辑

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

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



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

664571221 发表于 2022-9-13 10:21:44

虽然我看不懂,但是觉得高飞鸟是一个很认真的人

guosheyang 发表于 2022-9-13 15:48:51

本帖最后由 guosheyang 于 2022-9-13 17:18 编辑

关于a b值对换的那个函数个人认为,这样写也是可以的, 给函数传入的是 '(34) 返回的是'(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)



Source_Liu 发表于 2022-9-13 16:16:41

lisp最大的缺陷是与主流语言区别较大,使用人群交少。

guosheyang 发表于 2022-9-13 17:06:45

原文中 这句(setq x1) (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)) 等来处理。   .回复了几个我的看法,希望没有冒犯到高大师哈,我只是表达我的一点看法而已:lol

flythinking 发表于 2022-9-16 07:57:46

高版主讲解的非常透彻,谢谢大师指导

黄翔 发表于 2022-9-16 17:09:48

高大师,研究严谨.学习!

yjtdkj 发表于 2022-10-17 09:46:16

llsheng_73 发表于 2022-9-11 17:49
这一篇把lisp的陷阱讲得很透彻,认真研读理解后可以避免踩很多不必要的雷。

此外曾碰到过两类陷阱:


“二、传址的陷阱”这部分没太看懂,实参、形参是什么意思,楼主能否再讲明白一些呢?

llsheng_73 发表于 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而达到修改变量为函数返回值的目的
一般说传址的陷阱是指,传参过程并没有明确哪个参数需要按址传递,但函数返回值的同时,会对某些实参进行修改,修改的结果还不一定是所调用的函数的返回值,可能只是那个函数执行过程的一些过程数据,所以对于不太熟悉的函数需要多测试它,才可能发现它的问题,使用过程中避免它
页: 1 2 [3] 4 5
查看完整版本: LISP陷阱与缺陷