明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 5276|回复: 26

[函数] foreach的故事

  [复制链接]
发表于 2020-9-8 13:01:36 | 显示全部楼层 |阅读模式
今天分享一个函数foreach,在编制参数化自动绘图程序的时候,会用到多个变量设定初始数值,刚刚开始我 (setq text 100),dcl的就是 (set_tile "Text1" "2900"),
引用一段LL_J前辈的话:
函数是 AutoLISP 的灵魂,学习和使用 AutoLISP 的过程,从头至尾都贯穿着函数,
但在我的学习过程中,似乎一直似是而非似非而是,没有一个完整的概念,所以本文
也是个人的学习思考的小结,希望能给初学者一个整体的、朦胧的印象。
没有系统学习过,所以文中难免有理解错误,希望大家能海涵并提出批评指正。
如果把函数比作一道菜,AutoLISP 就是一桌大餐,有人追求的是美味,但我希望
AutoLISP 的爱好者们更追求这每一道菜的制作过程。”
在学习的过程中,有过茫然,有过失望,但在茫茫代码中,你的辛苦会有收获,记得
当年写出第一个代码时,喜悦开心的心情,就不用我说了。
其实我一直在想,写代码是为了什么,难道真是为了完成一个程序的喜悦吗,答案肯
定是否定的,一切都是为了工作,人这一辈子唯有工作挣钱养家停不下来。
抱歉哈,说了一堆不愿意听的,看下面的吧
在函数帮助里面是这样解释这个函数的
将表中的所有成员以指定变量的身份带入表达式求值
(foreach name list [expr...])
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))

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

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

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 2明经币 +2 收起 理由
USER2128 + 1 赞一个!
gaics + 1 很给力!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
发表于 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的学习也是有好处的。

点评

感谢版主的指导,不少函数都不知道怎么用。  发表于 2020-9-9 17:14
回复 支持 1 反对 0

使用道具 举报

发表于 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 | 显示全部楼层
感谢总结分享!学习了!
发表于 2020-9-8 17:11:44 | 显示全部楼层
谢谢楼主的幸苦分享经验,,  顶一下
发表于 2020-9-8 17:26:36 | 显示全部楼层
如果有2个表,两个表做不同的事情,那用foreach怎么写呢?

点评

相同的部分做一个foreach扩展函数,分别提取执行不同的表  发表于 2020-9-9 07:12
发表于 2020-9-8 17:31:20 | 显示全部楼层
对“函数是 AutoLISP 的灵魂”这句话特别的赞同。
发表于 2020-9-8 17:48:42 | 显示全部楼层
学习了,多个表又是什么情况?
发表于 2020-9-9 10:28:17 | 显示全部楼层
学习了,有些函数不好理解,就一直不用。哈哈,懒惰啊。
发表于 2020-9-10 15:38:53 | 显示全部楼层
感谢楼主分享,学习了
发表于 2020-9-10 21:56:30 | 显示全部楼层
foeach 这玩意 老早就知道,但是10多年前我不会用,一直懒惰也没有更新代码,最近实在扛不住了,改写代码才明白怎么用 哈哈
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-11-25 09:27 , Processed in 0.209287 second(s), 37 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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