autolisp的foreach和repeat函数
对于autolisp, 常见的一个说法就是autolisp是lisp语言的一种方言. 严格来说,
这种说法是不准确的, 因为autolisp缺少了lisp语言最引以为傲的macro宏,
连宏都没有自然是不能算作lisp的, 顶多算是 lisp-like
.
除了没有宏, autolisp还砍了lisp的不定长形参的这个特性, 所有的用户自定义函数的形参个数都是固定的, 不允许定义带有可选形参的用户函数. autolisp倒是内置了一些具有不定长形参的函数, 比如and/or之类的. 说是函数, 其实它们是special form, 因为它们的求值策略不同于普通函数, 但是autodesk用的术语就是function, 所以这里也用函数来称呼它们.
当然了, 并不是求值策略异于普通函数就一定是special form, 也可以是macro, 因为autolisp没有macro, 所以这些函数就只能是special form了.
foreach
和 repeat
, 就是两个很典型的 special form
.
foreach的用法是这样的, (foreach e lst body)
, 其中, lst
是一个 list
,
e
是 lst
的某个元素, body
是一些对 e
进行操作的表达式. 也就是说,
foreach
提供的是对list元素进行遍历操作的功能.
之所以说 foreach
不同于普通函数, 是因为 (foreach e lst body)
的 lst
是单次求值的,
仅仅在循环开始前求值1次, 循环开始之后不会再次对它进行求值, 无论要循环多少次都是如此的.
这种行为, 就是典型的macro的行为, 先执行宏展开再执行展开后的表达式.
while
就不是这样的, (while pred body)
的 pred
在每个循环当中都是要单独求值的,
而不是在循环开始前仅仅求值1次.
和 foreach
有类似表现的, 还有 repeat
. (repeat n body)
的 n
也是单次求值的,
仅仅在循环开始之前求值1次, 循环开始之后不会再次对它进行求值.
啰嗦了这么多, 搞清楚了 foreach 和 repeat 的特殊性, 有什么意义呢?
意义就在于有可能提高代码的运行性能. 因为autolisp是fp函数式编程语言, 任何表达式都有返回值, 这就导致代码往往可以写得十分随意, 可以随意到看不出来判断/循环之类的控制结构. 但是, 我们又无法控制代码的求值策略, 每个塞进去的入参都会被求值, 先求值再扔到函数里边, 这就可能导致多次重复求值的情况. 一旦出现了这种情况, 就意味着平白无故的性能损失. 通常, 我们可以使用局部变量做"中转", 可是, 这样一来又显得不那么fp了.
所以, 搞清楚内置函数(special form)的求值策略就很有必要了.
文章作者 Jack Hsu
上次更新 2024-12-22
许可协议 Copyright © Jack Hsu. All Rights Reserved.