hhh454 发表于 2020-9-8 13:01:36

foreach的故事

今天分享一个函数foreach,在编制参数化自动绘图程序的时候,会用到多个变量设定初始数值,刚刚开始我 (setq text 100),dcl的就是 (set_tile "Text1" "2900"),
引用一段LL_J前辈的话:
“函数是 AutoLISP 的灵魂,学习和使用 AutoLISP 的过程,从头至尾都贯穿着函数,
但在我的学习过程中,似乎一直似是而非似非而是,没有一个完整的概念,所以本文
也是个人的学习思考的小结,希望能给初学者一个整体的、朦胧的印象。
没有系统学习过,所以文中难免有理解错误,希望大家能海涵并提出批评指正。
如果把函数比作一道菜,AutoLISP 就是一桌大餐,有人追求的是美味,但我希望
AutoLISP 的爱好者们更追求这每一道菜的制作过程。”
在学习的过程中,有过茫然,有过失望,但在茫茫代码中,你的辛苦会有收获,记得
当年写出第一个代码时,喜悦开心的心情,就不用我说了。
其实我一直在想,写代码是为了什么,难道真是为了完成一个程序的喜悦吗,答案肯
定是否定的,一切都是为了工作,人这一辈子唯有工作挣钱养家停不下来。
抱歉哈,说了一堆不愿意听的,看下面的吧
在函数帮助里面是这样解释这个函数的
将表中的所有成员以指定变量的身份带入表达式求值(foreach name list )foreach 函数遍历表,将其中每一个元素依次赋给变量,并对每一个表达式求值。可以指定任意多个表达式。参数name表中元素将被赋给该名称指定的变量。list由要求值的元素组成的表。expr要对 list 中元素求值的表达式。返回值最后一次计算 expr 的结果。如果未指定 expr,foreach 返回 nil。
帮助里面的例子:我们只讲数值,我只用到数值,其他的应用需要前辈补充
(foreach n '(a b c) (print n))

返回
A
B
C C
相当于
(print a)
(print b) (print c)理解一下,也就是
(函数foreach   新的变量n    表'(a b c)    (分别打印表中的数值print   新的变量(对原表中的数值进行更新后的值) n))

讲一个直观的例子,相信大家都遇到多次偏移的时候
先来一个分段的,加强理解这个函数运行的过程
(defun c:tt (/ n)
(foreach n '(50 100 300 600)
(command "offset" n
(entsel "\n选择需要偏移的对象")
(getpoint "\n指定偏移方向一点") "")
      )
(princ)
)代码执行需要重复4次,选择4次对象,4次指定偏移点,偏移的距离就是 '(50 100 300 600)也就是说这个函数是以表中的个数来的。
问题来了,能不能点一次,自动偏移4次,当然是可以的,看下面
(defun c:tt2 (/ en pt n)
(setq en (entsel "\n选择需要偏移的对象")
      pt (getpoint "\n指定偏移方向一点"))
(foreach n '(50 100 300 600)
(command "offset" n en pt "");此处可以和上面的对比
      )
(princ)
)执行结果

这里已经能实现,点一次对象,偏移不同距离,其实foreach还有很多的妙用,论坛里面有不少
看到这里我相信你已经能理解这个函数的用法和运行的方式了,有的人说了,你这个距离都是以开始线为基准的
我需要的是已偏移后的线为基准(此处的线仅是代表),好的,再继续看下面
(defun c:tt3 (/ en pt n)
(setq en (entsel "\n选择需要偏移的对象")
      pt (getpoint "\n指定偏移方向一点"))
(setq x 0);先设定为0
(foreach n '(50 100 300 600)
(setq x (+ n x));这里意思就是在原有表中1数据+X=0+50,以此类推表2=50+100、表3......
(command "offset" x en pt "");此处可以和上面的对比
      )
(princ)
)执行结果

论坛里面有很多的前辈,免费发布自己的函数,他们真的是无私的人,给他们点赞,别看就几行代码,给你带来的是经济效益,也有可能成为你
养家的资本(哈哈,又说到这个上面了)。
最后我把源码放上来,不想复制的就下载

e2002 发表于 2020-9-9 09:21:11

本帖最后由 e2002 于 2020-9-9 14:02 编辑

foreach ,就是 for each ,对list中的每一个item做同一些事。

foreach , 也就是其他语言中的 for 循环控制。当然,你也可以用 iCount 作为循环计数器,改写为等价的 repeat或while循环。

python中的 for 与 lisp 的foreach 基本是同样的含义。

lisp中还有一个与foreach 很类似的功能函数 : mapcar

如果你是需要对 list中的每一个item做处理,并返回处理后的结果list(和源list一一对应的一个结果list),你就应该使用 mapcar ,而不是使用 foreach(当然也是可以的,但不如 mapcar 具有显著的“LISP编程风格”)。

关于函数式编程 与面向对象编程, 这个要说起来就太多了,不是大牛也说不清楚。我们一般的业余编码的,用就是了。python 中同样提供了 mapcar 等很多 LISP的功能, 如果有 LISP的编程基础,对于 python的学习也是有好处的。

wzg356 发表于 2021-11-15 22:14:02

本帖最后由 wzg356 于 2021-11-15 22:31 编辑

再深一点,欢迎补充

如果只是主贴用法,mapcar也可以,mapcar难理解一点

mapcar foreach执行过程一样

区别
mapcar每次执行功能只能以一个函数表达式书写
foreach每次执行功能可多个表达式顺序书写

mapcar返回以表形式展示每一步的结果
foreach只能返回最后一次的结果

例如
(setq y 5)
(foreach x (list 1 2 3 )(setq y(+ y x)))
-----------------------------------------
(setq y 5)
(mapcar '(lambda(x)(setq y(+ y x)))(list 1 2 3 ))

二者最终可以得到一样的y

明_明 发表于 2020-9-8 13:29:56

感谢总结分享!学习了!

999999 发表于 2020-9-8 17:11:44

谢谢楼主的幸苦分享经验,,顶一下

烟盒迷唇 发表于 2020-9-8 17:26:36

如果有2个表,两个表做不同的事情,那用foreach怎么写呢?

lzy233 发表于 2020-9-8 17:31:20

对“函数是 AutoLISP 的灵魂”这句话特别的赞同。

mokson 发表于 2020-9-8 17:48:42

学习了,多个表又是什么情况?

jinan1913 发表于 2020-9-9 10:28:17

学习了,有些函数不好理解,就一直不用。哈哈,懒惰啊。

Sonnenblumen 发表于 2020-9-10 15:38:53

感谢楼主分享,学习了:handshake

muwind 发表于 2020-9-10 21:56:30

foeach 这玩意 老早就知道,但是10多年前我不会用,一直懒惰也没有更新代码,最近实在扛不住了,改写代码才明白怎么用 哈哈:L
页: [1] 2 3
查看完整版本: foreach的故事