用作com的LAMBDA表达式
我的一本关于AutoLISP/Visual LISP的书的读者要求对此主题进行解释。因为我相信这可能是大家都感兴趣的,我想分享我的答案。
这是我在我的博客lispexpert中发表评论的答案。blogspot。通用域名格式:
几天前,一位读者问我:
我完全被第74页的最后一个函数难住了:
(定义排序列表(lst func)
(mapcar’(λ(x)(第n x第lst))
(vl-sort-i lst func)))
;;;清单5.8。列表排序功能。
我不明白的是
“(λ(a b)(
用作排序列表中的“func”参数,以及如何将其应用于defun的底层(vl-sort-i lst func)部分。
您的问题归结为一个问题:Visual LISP排序函数如何工作?
Vl sort和Vl-sort-i操作称为比较排序。这意味着它读取两个列表元素,通过提供的比较运算符对其进行比较,以找出这两个元素中的哪一个应该首先出现在最终排序的列表中。可以使用许多算法来实现这一点,内部使用的算法没有文档记录。有关比较排序算法主题的更多信息,请参见http://en.wikipedia.org/wiki/Comparison_sort.
但是让我们看看vl-sort和vl-sort-i是如何工作的。当它们使用比较排序算法时,它们取一对值并对其应用比较运算符。这意味着它们通过每次比较列表中的两个术语并根据所实现的排序算法执行某种重新排序来重复操作。
你说过:
“我不明白的是,lambda(a b)(
之所以可以这样做,正是因为vl-sort和vl-sort-i每次都从列表中获取一对参数。这些参数是lambda函数用符号a和b标识的参数。
让我们为一个符号指定一系列点,比如lst。因为我们只比较每个子列表的第一项,其他值不重要,所以我们只使用零。可以是任何数字:
(setq lst’((9 0 0)(2 0 0)(6 0)(4 0 0)(7 0)))
为了检查排序函数每次比较哪些数字,我们将修改lambda表达式,以便它也将接收到的值作为a和b打印到控制台。这将通过将第一个car嵌套在打印表达式中,将第二个car嵌套在princ表达式中来完成。这样,打印将在a的值之前引入一行新行,并在其后面引入一个空格。然后princ将输出打印在同一行中的b值。这样,每个周期中比较的值将打印在不同的行上。
_$(vl sort lst’(lambda(a b)(print(car a))(princ(car b)))))
2 9
7 4
4 6
7 6
4 2
4 9
6 9
7 9((2 0 0) (4 0 0) (6 0 0) (7 0 0) (9 0 0))
如我们所见,vl sort检查以下关系以对列表进行排序:
如果2小于9,
如果7小于4,
如果4小于6,
如果7小于6,
如果4小于2,
如果4小于9,
如果6小于9,
如果7小于9。
在最后一对数字之后,vl sort返回排序列表,在本例中为排序点列表。
如果我们使用vl-sort-i进行相同的操作,唯一的区别是返回的列表将不包括点子列表,而是包括它们的索引。这就是为什么使用第n个函数处理返回的列表以恢复由这些索引标识的子列表。那么为什么要使用vl-sort-i呢?据记录,在某些情况下,vl sort将删除重复条目。这样我们可以保证在分拣过程中不会丢失任何物品。
Vl sort和Vl-sort-i是AutoLISP的受欢迎的新增功能。在Visual LISP之前,我们必须编写自己的排序函数。正如Reini Urban所说,“一般来说,在普通AutoLISP中进行排序是一件令人头痛的事”。http://autocad.xarch.at/lisp/#sort 多哥先生,
我知道这个帖子很老了,但我想感谢你创建它并分享这些信息。
至于我自己,谁开始学习如何处理vl-sort/vl-sort-i函数,我想为什么没有一个函数
而且
您的(排序列表)示例函数就是这样做的:
_$
(defun sort-list (lst func)
(mapcar (function (lambda (x) (nth x lst)))
(vl-sort-i lst func)
)
)
SORT-LIST
(setq StrLst '("A" "C" "B" "E" "A" "D" "B" "A" "C"))
("A" "C" "B" "E" "A" "D" "B" "A" "C")
_$ (vl-sort-i StrLst (function (lambda (a b) (< a b))))
(7 4 0 6 2 8 1 5 3)
_$ (vl-sort StrLst (function (lambda (a b) (< a b))))
("A" "A" "A" "B" "B" "C" "C" "D" "E")
_$ (sort-list StrLst (function (lambda (a b) (< a b))))
("A" "A" "A" "B" "B" "C" "C" "D" "E")
_$ (setq IntLst '(10 30 20 40 10 50 20 10 30))
(10 30 20 40 10 50 20 10 30)
_$ (vl-sort-i IntLst (function (lambda (a b) (< a b))))
(7 4 0 6 2 8 1 3 5)
_$ (vl-sort IntLst (function (lambda (a b) (< a b))))
(10 20 30 40 50)
_$ (sort-list IntLst (function (lambda (a b) (< a b))))
(10 10 10 20 20 30 30 40 50)
我曾想过编写这样的函数(我没有想到(lambda(x)(nth x lst))部分),但现在我发现这样的函数是存在的。
另一个精彩的例子是展示如何将函数用作子函数中的参数。
我不知道你是否仍然活跃在这个论坛,但我很惊讶,这个帖子没有得到任何回复,关于这一点。所以我重新启用它,因为它将对像我这样的学习型用户有所帮助。 FWIW,请注意,示例中不需要lambda函数,因为只有一个函数使用两个参数进行求值:
_$ (vl-sort '(6 2 7 4 8 9) '<)
(2 4 6 7 8 9)
我知道你的第二个例子,但我试图这样做:
;使用(vl-sort-i)保留重复整数(具有类似vl排序的结果):_1$(setq Lst’(6 2 7 2 4 1 8 9))(6 2 7 2 4 1 8 9)_1$(mapcar’(λ(x)(nth x Lst))(vl-sort-i Lst'
页:
[1]