77077 发表于 2014-5-7 10:07:44

求大师指点指点mapcar和foreach

代码:
(setq lst (list 10 20 30))
(mapcar '1+ lst)
(foreach n lst (1+ n))

CAD运行:
命令: (setq lst (list 10 20 30))
(10 20 30)
命令: (mapcar '1+ lst)
(11 21 31)
命令: (foreach n lst (1+ n))
31

个人小结:
共同点,好像都可以将lst中的元素拿去分别运算.
不同点,mapcar返回运算后的新表,foreach只返回最后一个值.

问题:
谁能详细帮我解释下两者的区别于联系,以及两者的具体适用环境.

ll_j 发表于 2014-5-7 10:36:34

看看我数字签名中的“认识自定义函数”,或许会有帮助。

edata 发表于 2014-5-7 11:22:02

个人理解mapcar=(list(1+ 10)(1+ 20)(1+ 30))
foreach=(1+ 10)(1+ 20)(1+ 30)
mapcar=(setq lst '())(foreach n '(10 20 30) (setq lst(cons (1+ n) lst)))
(setq lst(reverse lst))
mapcar配合lambda可以计算多个表
计算中点(mapcar '(lambda(x y)(*(+ x y) 0.5)) p1 p2)
.........

llsheng_73 发表于 2014-5-7 12:10:28

个人对mapcar和foreach的理解如下:
首先它们运行的过程是一样的,但返回的结果不一样
以(mapcar '1+ '(10 20 30))来说,它把'(10 20 30)的每一个元素作为参数进行 1+,并且根据调用参数的顺序把结果放到一个表里边返回,得到'(11 21 31)
(foreach n '(10 20 30) (1+ n)) 它同样是把'(10 20 30)的每一个元素传递给n进行1+,但最后只返回了31,但并不是前两个它就没有运行。只不过它是返回了循环内部最后一个语句的最后一次运行的结果而不是象mapcar那样把全部结果放在一个表里边返回,个人认为这是它们的根本区别
另外可处理的表的个数不一样
就象板凳上的edata说的,mapcar可以处理多个表,而foreach虽然也可以但不是这么直接
比如(mapcar 'list '(1 2 3)'(a b c))==>((1 A) (2 B) (3 C))
这个用foreach虽然也可以做到但明显要麻烦得多
(setq lst nil)(reverse(foreach x'(1 2 3)(setq lst(cons(list x(nth(vl-position x'(1 2 3))'(a b c)))lst))))
另外,关于什么时候要加上'(lambda(x1...xn)...)这根据具体需要,一般说来,如果操作比较复杂,或者所涉及操作需要的操作数不能全部由后边的表提供就需要
比如'(10 20 30)每一个元素都加上2,这个时候就不能(mapcar '+ 2 '(10 20 30))而应当
(mapcar '(lambda(x) (+ 2 x))'(10 20 30)),这就是因为+这个操作所用到的操作数之一2不是由表来提供的,当然也不用lambda来做到(mapcar '+ '(10 20 30) '(2 2 2))这又是因为+这个操作所需要的操作数全部通过表提供的
所以板凳上的edata兄弟关于mapcar配合lambda可以计算多个表的说法并不十分准确
以上只是个人粗浅认识,不足之处希望指正

ll_j 发表于 2014-5-7 12:35:23

两者都是遍历,速度也差不多(mapcar稍快但有限),最大的差别是结果的不同,mapcar是对表每个元素运算,并“返回”所有的结果,foreach则是仅返回最后一个结果,其实不返回也是一样,因为foreach注重的是“过程”,帮助文件中对foreach举例的函数是princ,这是关键,遍历完成,打印也完成,返回值其实是无意义的。

edata 发表于 2014-5-7 15:13:44

llsheng_73 发表于 2014-5-7 12:10 static/image/common/back.gif
个人对mapcar和foreach的理解如下:
首先它们运行的过程是一样的,但返回的结果不一样
以(mapcar '1+ '(10 ...

是的,是否支持多个表处理取决于函数是否支持。+ - * / max min ......
如果是函数 ~abs ascii......这类只计算一个元素的只能处理一个表中的元素。
(mapcar 'ascii '("a" "b" "c"))
=> (97 98 99)
(mapcar 'ascii '("a" "b" "c") '("a" "b" "c"))
=>; error: too many arguments
mapcar 即取出所有表中相应顺序的元素给 前面设定的函数作为参数。

langjs 发表于 2014-5-7 15:28:25

还是没学会mapcar的用法。

langjs 发表于 2014-5-7 15:30:54

貌似懂了一点,谢谢各位的讲解

77077 发表于 2014-5-8 10:56:44

看过之后还是觉得似懂非懂.让我再练习练习~~

77077 发表于 2014-5-8 11:53:05

本帖最后由 77077 于 2014-5-8 12:04 编辑

;将双层表中的元素按列拼接
;-------------------------------------
(setq lst1 (list "R1" "R2" "R3")
      lst2 (list "一类居住" "二类居住" "三类居住")
      lst (list lst1 lst2)
)
;---------------------------------------
;用mapcar写成功.
(mapcar 'strcat (nth 0 lst) (nth 1 lst))
==>("R1一类居住" "R2二类居住" "R3三类居住")

问题1:如果用foreach怎么写呢?

问题2
(setq lst '(("R1" "一类居住" "40%") ("R2" "二类居住" "35%") ("R3" "三类居住" "30%")))
我要得到("R1一类居住" "R2二类居住" "R3三类居住"),如何写呢?
页: [1] 2
查看完整版本: 求大师指点指点mapcar和foreach