我试图使用标准循环设施来收集结果,但它只返回 nil。为什么是这样?感觉这应该有效:
(defun coll-intersects (bounds mv)
(let ((res (list))
(loop for x from (first bounds) to (+ (first bounds) (third bounds)) do
(loop for y from (second bounds) to (+ (second bounds) (fourth bounds))
if (not (member (cl-byte (aref mapa x y)) mv))
collect (aref mapa x y) into res
))))
Run Code Online (Sandbox Code Playgroud)
但不,我必须这样做:
(defun coll-intersects (bounds mv)
(let ((res (list)))
(loop for x from (first bounds) to (+ (first bounds) (third bounds)) do
(loop for y from (second bounds) to (+ (second bounds) (fourth bounds))
do
(if (not (member (cl-byte (aref mapa x y)) mv))
(push (aref mapa x y) res))
))
res))
Run Code Online (Sandbox Code Playgroud)
为什么?我真的很困惑为什么第一个不起作用
小智 6
正如埃文斯的回答所说,问题是
(loop ...
collect ... into x
...)
Run Code Online (Sandbox Code Playgroud)
绑定x。这个构造的目的真的是让你可以收集多个列表:
(defun partition (l)
(loop for e in l
if (evenp e)
collect e into evens
else
collect e into odds
finally (return (values evens odds))))
Run Code Online (Sandbox Code Playgroud)
例如。
如果您想从嵌套循环中收集单个列表并且您关心顺序,您可以使用以下技巧:
(defun sublist-evens (l)
(loop for s in l
nconcing
(loop for e in s
when (evenp e)
collect e)))
Run Code Online (Sandbox Code Playgroud)
这里外循环本质上nconc是将内循环的结果放在一起。这当然可以嵌套:
(loop ...
nconcing
(loop ...
nconcing
(loop ...
collect ...)))
Run Code Online (Sandbox Code Playgroud)
将工作。也有可能它loop足够聪明,可以将尾指针指向它正在使用nconc/构建的列表nconcing,尽管您必须检查它。
但是,如果您想从某个深层嵌套循环(或任何其他搜索过程)中按顺序构建一些列表,我发现使用收集宏来做到这一点几乎总是更令人愉快(免责声明:我写了这个)。有了这样一个宏,上面的sublist-evens函数看起来像这样:
(defun sublist-evens (l)
(collecting
(dolist (s l)
(dolist (e s)
(when (evenp e) (collect e))))))
Run Code Online (Sandbox Code Playgroud)
和
> (sublist-evens '((1 2 3) (4 5 6)))
(2 4 6)
Run Code Online (Sandbox Code Playgroud)
你可以做得更好:
(defun tree-partition (tree)
(with-collectors (evens odds)
(labels ((search (it)
(typecase it
(list
(dolist (e it)
(search e)))
(integer
(if (evenp it)
(evens it)
(odds it)))
(t
(warn "unexpected ~A" (type-of it))))))
(search tree))))
Run Code Online (Sandbox Code Playgroud)
现在
> (tree-partition '(((1 2 3) (4)) 5))
(2 4)
(1 3 5)
Run Code Online (Sandbox Code Playgroud)
(对于 hack 值,您可以使用另一个宏来更简洁地表达上述内容:
(defun tree-partition (tree)
(with-collectors (evens odds)
(iterate search ((it tree))
(typecase it
(list
(dolist (e it)
(search e)))
(integer
(if (evenp it)
(evens it)
(odds it)))
(t
(warn "unexpected ~A" (type-of it)))))))
Run Code Online (Sandbox Code Playgroud)
免责声明:我也写了那个宏。)
| 归档时间: |
|
| 查看次数: |
58 次 |
| 最近记录: |