Autolisp是怎样区分表与函数调用的?
本帖最后由 wrf610051 于 2020-10-1 17:08 编辑(setq L 70 D 20)
(setq tj (list < L D))
(setq ans (cond (tj
"Yes")
(T
"No")
))
;;想返回"No",但得到的是"Yes"。因为AutoLisp把tj认成了表,如何告诉它tj是函数调用呢?;;是不是cond后面的表达式,不会求值呢?
(setq L 70 D 20)
(setq tj (list < L D))
(setq ans (cond ((eval tj)
"yes")
(T
"No")
)) (setq tj (list < L D)) 改为 (c: tj (list < L D))
猜的 start4444 发表于 2020-10-1 10:18
(setq tj (list < L D)) 改为 (c: tj (list < L D))
猜的
我写错了,想得到"No",因为(< 70 20)按条件表达式应为nil,但它把(< 70 20)看成一个表。 start4444 发表于 2020-10-1 10:18
(setq tj (list < L D)) 改为 (c: tj (list < L D))
猜的
试了,还是得不到想要的结果。
(setq L 70 D 20)
(setq tj (list < L D))
返回:(#<SUBR @0000000029078a48 <> 70 20)
;;说明它已经把tj认为是一个函数了?下一句它为什么不按函数求值呢?
(setq ans (cond (tj "yes") (T "No")))
;返回:"yes" 本帖最后由 wyl219 于 2020-10-1 18:28 编辑
wrf610051 发表于 2020-10-1 17:21
试了,还是得不到想要的结果。
(setq L 70 D 20)
(setq tj (list < L D))
(#<SUBR @0000000029078a48 <> 70 20) 这种是列表#<SUBR @000000002e938a48 <> 这种才是函数.
如果是提前赋值,就想你示例的函数那样,那直接把list去掉,tj保存判断后的布尔值就好.就像下面这样:
(setq L 70 D 20)
(setq tj (< L D))
(setq ans (cond (tj
"Yes")
(T
"No")
))
如果是想提前设定这个函数,再后面多次修改调用,可以把他写成函数.类似这样
(defun tj() (< L D))
(setq L 70 D 20)
(setq ans (cond ((tj);这里tj是个函数,要用括号括上
"Yes")
(T
"No")
))
如果tj的内容比较简单,可以考虑用lamba函数,就像这样.
(setq tj (lambda () (< L D)))
(setq L 70 D 20)
(setq ans (cond ((tj);这里和上面一样,要用括号括上
"Yes")
(T
"No")
))
还有一种方式,用read函数配合eval函数,注意tj保存的是字符串而不是列表.
(setq tj "(< L D)") ;这里没有list,否则后面会当成一个list函数
(setq L 70 D 20)
(setq ans (cond ((eval (read tj))
"Yes")
(T
"No")
))
注意,还有一种方式,即只使用eval不用read,像下面这样:
(setq L 70 D 20)
(setq tj (list < L D))
(setq ans (cond ((eval tj)
"Yes")
(T
"No")
))
单纯这样运行是没问题的,但是tj里保存的实际是 (< 70 20)这个列表,即用70和20代替L和D,然后在后面执行,如果之后修改L和D,对后面的执行没有影响的.因此tj里保存的是常量而非变量.
而用read函数,里面保存的是L和D的字符串,执行的时候才会调用L和D的值.
以上几种方式,lamba是更为正统的方式.
另外,可以猜一下下面的代码的输出值,如果弄清楚了,可能对你现在的疑惑有所帮助.
(defun tj() nil);一个返回值为nil的函数
(princ tj) ;打印tj变量保存的内容
(princ (tj)) ;打印tj函数的返回值
本帖最后由 e2002 于 2020-10-3 10:29 编辑
LISP中:函数就是list。
上面回复中说了,需要使用 eval 对 list 求值。
但eval这个函数时运行时求值,所以 不要 用在 需要最后编译为 vlx/fas的 AutoLISP源代码 中, 否则极大可能出错。
之前也遇到的一个类似的问题,函数名称的参数传递,在源码中没有问题,但编译后再运行就是出错。
今天有点时间,总算找出了bug产生的原因,可能也是这种运行时求值的问题,编译时,由于不是运行,link无法获得内部函数的函数指针,只能获得 nil ,错误就此发生。
这个bug非常罕见,有时间我再深入琢磨之后,找时间写一个专门的文章。
;;======= Update ===========
在各位大神的指导下,对这个问题基本搞清楚了。
由于编译选项选上了“优化模式”与 “定位变量”,源码在编译时,内部函数也一起处理了,所以无法获得按原有的函数名称传递参数。
办法就是把内部函数移出去作为普通的函数。
在此一并谢谢各位!
原地踏步解决了我的问题;
wyl219讲得很详细,让我明白了原由;
e2002讲到了涉及更深层次内容,我暂时无法理解。 wrf610051 发表于 2020-10-2 09:36
在此一并谢谢各位!
原地踏步解决了我的问题;
wyl219讲得很详细,让我明白了原由;
当你给一个变量赋值的时候,会直接赋给其真实值,所以直接eval变量等同于直接赋值布尔值.
下面这个例子:
(setq L 70 D 20)
(setq tj (list < L D)) ;先赋值
(setq L 20 D 70);再修改变量
(if (= (eval tj) (< L D));tj里面的数据会跟着L D的值走么?
(print "yes")
(print "No")
)
页:
[1]