明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
12
返回列表 发新帖

[提问] (apply 'mapcar '(list (10 20) (30 40) (50 60)))表达式详解

  [复制链接]
 楼主| 发表于 2015-9-14 19:19:00 | 显示全部楼层
ll_j 发表于 2015-9-14 12:32
理解基本是正确的,但实际说等同,其实也并不完全等同,这句代码的精髓其实是apply的使用:这是我早期的一 ...

嗯 好 我仔细领悟领悟
回复

使用道具 举报

发表于 2015-9-16 23:27:35 | 显示全部楼层
ll_j 发表于 2015-9-14 12:32
理解基本是正确的,但实际说等同,其实也并不完全等同,这句代码的精髓其实是apply的使用:这是我早期的一 ...

刚才试了一下用eval会出错而apply则不会
不知道大大能不能说说这个直观的对表直接赋予运算函数的意思?
用eval为什么会出错而apply则不会,两者的运算机制有什么不一样么?
我只知道eval是返回 AutoLISP 表达式的求值结果,而apply是将表传递给指定的函数
谢谢,不胜感激!
回复

使用道具 举报

发表于 2015-9-17 14:20:43 | 显示全部楼层
重慶崽兒 发表于 2015-9-16 23:27
刚才试了一下用eval会出错而apply则不会
不知道大大能不能说说这个直观的对表直接赋予运算函数的意思?
...

eval 函数是对表达式求值,操作对象就是后面的表达式,有点像程序运行的语言解释器,通俗一点比喻,就像我们说“1+1”,这实际上是一个“字串”(表达式),只有我们头脑中把这个字串理解为“2”,这个表达式才是“2”,这个理解过程就是这个eval,否则,这只能是个字串。一般情况下,语言解释器是会自动“解释”的,但有时我们会强制的把按某种规则堆叠的结果认为是字串(程序中的表达式),这时,如果想知道这个字串(表达式)的值,就需要eval来“强行”解释。当然,表达式和字串的不同的,但在这个问题上,是可以比喻的。
apply 则需要两个参数,前一个是函数名,后一个是表,而且这个表应该是和前面的函数名有对应关系,某种意义上来少,后面的函数名和表应该可以构成一个完整的表达式,但因为表达式的规则,其实并不是简单构成,这也就是使用eval出错的原因。
对于eval的理解,可以看看我签名中的认识自定义函数,最后部分有对表达式的一部分引申理解,或许对你能有用。
回复

使用道具 举报

发表于 2015-9-17 18:57:09 | 显示全部楼层
谢谢稽前辈的回答,虽然还是没明白为什么会出错
对于eval,我现在的理解就是“强行解释”这四个字,如:
(setq a (list 1 2 3))
(setq b 'a)
(eval b)
=>
(1 2 3)
(eval (setq a 123))
=>
123
但是直接(eval (setq a (list 1 2 3)))会出错:
; 错误: 函数错误: 1
eval是返回对表达式求值的结果,难道这个结果不能是表?
PDF已经下载了,正在研读,肯定会有很大的帮助
再次感谢稽前辈不吝解答,小子愚笨,或许之后还会叨扰,勿怪
回复

使用道具 举报

发表于 2015-9-18 07:35:45 | 显示全部楼层
重慶崽兒 发表于 2015-9-17 18:57
谢谢稽前辈的回答,虽然还是没明白为什么会出错
对于eval,我现在的理解就是“强行解释”这四个字,如:
( ...

eval 的参数表达式必须是能求值的,可以的一个不求值的表达式,比如 '(setq a (list 1 2 3)) ,也可以是一个可以求值的表达式,比如 (setq a '(list 1 2 3)) ,这两个式子看上去差不多,但还是有点区别的,在解释器中,这是两个完全不同的东西,第二个式子会直接得到结果 '(LIST 1 2 3) ,而第一个则只是一个完整的表达式。
我们再看看你的式子: (eval (setq a (list 1 2 3))) ,出错,再看看 (eval '(setq a (list 1 2 3))) 或者 (eval (setq a ’(list 1 2 3))) ,结果都不会出错,看出点差别了没?就是那个小撇('=quote),这是强制不求值的意思,有了这个全部或局部的“不求值”,才能保证eval 的正确。
再来看看 (eval (setq a (list 1 2 3))) 到底错在哪里,按由内到外的原则,这个表达式先计算 (setq a (list 1 2 3)) ,其结果是表 (1 2 3) ,再对这个表进行eval 求值,按照Lisp的规则,会将表的第一个元素看出函数名,而 1 不是函数名,所以出错是必然的。
这里说了求值和不求值的差异,但eval 的参数并不是一定要不求值,比如 (eval (setq a 1)) ,返回结果就是1,参数并不一定要不求值,但多数情况下,对不含不求值表达式进行eval是没有什么意义的。
怎么说呢,或许的对语言还理解的不够透彻,有些函数还真没办法用很容易理解的语言描述清楚,但用多了,自然会慢慢体会,eval 也是其中一个。
一个技巧:测试函数或者语句的时候,适当使用type函数,可能更容易理解。
回复

使用道具 举报

发表于 2015-9-18 20:04:32 | 显示全部楼层
ll_j 发表于 2015-9-18 07:35
eval 的参数表达式必须是能求值的,可以的一个不求值的表达式,比如 '(setq a (list 1 2 3)) ,也可以是一 ...

谢谢稽前辈,好像有点感觉了,我下去在好好理解下
现在的理解是:eval返回值为:判断(解释)表达式后的值。
如:(eval (setq a 1))与(eval '(setq a 1))
由内而外,前者,eval直接解释1,所以返回1,后者eval解释(setq a 1) 所以也返回1
再如:(eval (setq a (list 1 2 3)))与(eval (setq a '(list 1 2 3)))或者(eval '(setq a (list 1 2 3)))
前者,eval解释表(1 2 3),eval若遇到表,则将此当成表达式,而表(1 2 3)无法解释,所以出错
后两者,eval解释(list 1 2 3)和(setq a (list 1 2 3)),返回(1 2 3)
还有就是:eval只能解释一层,若还需要解释,就还得加eval
如:(eval (eval '(setq a '(list (list 1 2 3)))))
综上所述,eval就是:将跟在eval后面的参数和表达式(虽然也是参数,单独写出来好理解)强行解释出来,若遇到表,则当成表达式。
稽前辈这句话:eval 的参数表达式必须是能求值的,不知道将“求值”二字改成“解释”是不是更好。
不知道这样理解对不对
再次谢谢稽前辈
回复

使用道具 举报

发表于 2017-7-29 10:15:36 | 显示全部楼层
本帖最后由 jpg102329 于 2017-7-29 10:18 编辑

(APPLY 'mapcar (cons 'list lst))

(APPLY 'vlax-curve-getclosestpointto (entsel))
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-15 07:00 , Processed in 0.156060 second(s), 17 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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