如何解决我需要帮助来理解一个找到列表深度的 lisp 程序 使用 depth声明式方法
我需要帮助从理论上理解我的代码。这是我的 lisp 程序:
(defun depth (lst)
(if (or (null lst) (atom lst)) 0
(+ 1 (apply 'max (mapcar #'depth lst)))
))
我知道它适用于这个例子:
(write (depth '((a (b c) d r ((t))))) -> 3
我只是无法理解我尝试过的 IF
语句的 else 语句。
如果您能帮助我,将不胜感激。提前致谢。
解决方法
这是您的代码,稍微重新格式化:
(defun depth (value)
(if (or (null value) (atom value))
0
(+ 1 (apply 'max (mapcar #'depth value)))))
我将 lst
(顺便说一下,您可以将它写成 list
)重命名为 value
,因为名称令人困惑,因为它表明变量始终是一个列表,不是真的。可以对任何值调用函数 depth
:
(depth "hello")
=> 0
(depth 100)
=> 0
当 if
为 NIL 或任何 value
时,会评估 atom
的 then 分支。由于 NIL
也是 atom
,测试表达式可以简化为 (atom value)
。当 value 是一个原子时,深度为零。
当 if
不是原子时评估 value
的 else 分支,atom
的 by definition 表示 {{1} } 这里是一个value
。该函数还假定它是一个适当的列表,而不是某个循环列表。
由于 cons
是该分支中的一个列表,我们可以对其调用 value
:mapcar
;这是函数假定列表正确的地方。
这为 (mapcar #'depth value)
中的每个 (depth v)
计算 v
。更准确地说,如果 value
是一个长度为 n 的列表,那么对 value
的调用评估为一个数字列表 mapcar
,其中 (D1 ... Dn)
是 { {1}} 用于 1 和 Di
之间的所有 (depth Vi)
。
所以我们知道 i
对于某些数字列表 n
是 (apply 'max (mapcar ...))
。一般:
(apply 'max depths)
... 是一种调用由 depths
表达式表示的函数对象的方法,该表达式至少包含 (apply fn v1 ... vn list)
个元素(fn
到 n
),以及v1
中存储的任意数量的附加元素。当您引用函数时,如 vn
,或者当您编写 list
时,您在函数命名空间中通过名称引用函数。
将此与调用函数的通常方式进行对比:
'max
函数名称和传递的参数数量是固定的:一旦读取表单,我们就知道有一个带有 3 个参数的 #'max
调用。
(f x y z)
函数是一个内置函数,允许您在列表中的最后一个调用参数中传递其他参数。上面的调用可以写成:
f
这也可以写成:
apply
唯一的区别可能是运行时效率的问题(而且对于好的编译器,也许没有区别)。
在你的例子中,你这样做:
(apply #'f x y z ()) ;; note the empty list as a last argument
这与编写(伪代码)相同:
(apply #'f (list x y z)) ;; all arguments in the last list
... 其中 (apply max depths)
是列表 (max d1 d2 d3 ... dn)
。
但是我们不能直接把它们全部写出来,因为列表的内容只有在运行时才知道。
因此,apply 调用计算递归计算的所有深度中的最大深度。请注意,上面对 depths
的使用有些不当,因为不应使用任意大小的列表调用 (list d1 d2 ... dn)
:名为 CALL-ARGUMENTS-LIMIT
的标准中有一个限制,允许理论上低至 50,这是此类列表的最大大小(我们将在下面看到替代方案)。
最后,apply
根据此结果计算 apply
。换句话说,整个表达式可以概括为:列表的深度是其所有元素的最大深度加1。
使用 depth
代替 (+ 1 ...)
,您可以使用 REDUCE
在列表上连续计算 reduce
。这比 apply
更可取,因为:
-
元素数量没有限制,比如
max
apply
-
不需要构建深度的中间列表,您遍历值列表,调用
apply
并直接使用结果来计算最大值。骨架是:(reduce 'max depths) ;; works the same,but more reliably
声明式方法
代替 depth
,(reduce (lambda (max-so-far item) ...)
value
:initial-value 0)
宏可以用作更易读的替代方法来表达相同的计算。我还使用了 reduce
,我认为这使意图更清晰:
loop
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。