【问题标题】:Flattening a tree structure in Lisp在 Lisp 中展平树结构
【发布时间】:2013-11-22 11:36:51
【问题描述】:

我正在努力扁平化树结构。我通过将每个原子符号与树中的其余部分进行比较来递归地执行此操作,但是,我的一个朋友建议使用以下代码,我认为它看起来更干净。我只是不明白这行:

((atom tree)(list tree))

我了解他们每个人分别做什么,我也知道下面的循环需要一个列表或者它会导致错误,我怀疑这有很多原因是我们将符号转换为列表 if atom返回真。但我仍然觉得我没有完全理解代码。

(defun flatten (tree)
(cond ((null tree)
     nil
     )
    ((atom tree)(list tree))
    (t
     (loop for a in tree appending (flatten a)))))

如果有人能抽出时间来解释一下会很棒吗?谢谢!

【问题讨论】:

标签: list recursion tree lisp


【解决方案1】:

代码的格式很差。在你问题的第一部分,根本不清楚为什么

((atom tree) (list tree))

会出现在任何 Common Lisp 代码中,因为它看起来像是在尝试调用(atom tree),取回一个函数,然后用(list tree) 调用该函数。在上下文中,通过适当的格式,它会更清晰:

(defun flatten (tree)
  (cond 
   ((null tree) nil)
   ((atom tree)(list tree))
   (t (loop for a in tree
            appending (flatten a)))))

这是cond 中的一个子句。它说 if tree 是一个原子(可以是一个符号、一个数字、一个向量等,任何不是 cons 的东西),然后返回 (list tree) .正如larsmans explainedflatten 应该总是返回一个列表,这确保了(flatten 3),例如,将返回(3)。由于(loop for a in tree ...) 适用于任何作为列表的tree,因此实际上没有必要为(null tree) 提供案例,因为nil/() 一个列表。这个定义可以简化为:

(defun flatten (tree)
  (if (atom tree)
      (list tree)
      (loop for a in tree
            appending (flatten a)))))

Stack Overflow 上有一些类似的问题,有些问题的代码与您发布的内容几乎相同(以格式为模)。朋友是否基于其中一个建议。无论如何,为了完整起见,您可以看看:

【讨论】:

  • 感谢您的回答。由于额外的括号,第二个 flatten 函数会引发错误。
【解决方案2】:

我也知道下面的循环需要一个列表,否则会导致错误,我怀疑这有很多原因是因为如果 atom 返回 true,我们将符号转换为列表。

准点。 flatten 的后置条件是它的结果总是一个平面列表(不是“平面列表或原子”),因此递归调用只需要处理一种数据类型。

【讨论】:

    【解决方案3】:

    ((atom tree)(list tree)) 是一段无法单独理解的语法。它属于cond 语法:它在 Lisp 文化中被称为 cond pair。 cond 对表示如果(atom tree) 表达式为真,则评估(list tree)cond 然后终止并返回该值。

    cond 对 术语不精确,因为在 Common Lisp 中,cond 子句是 n 元的。它们不必成对。额外的形式可以完全省略,因此子句是单项,允许 condor 一样使用:

    (cond (a) (b) (c) ...) <==> (or a b c)
    

    在这里,a 被评估。如果它产生 true(非 nil 的值),则 cond 停止并返回 a 的值。否则它会测试b 等等。这正是or 所做的。

    可以有两种或多种形式:

    (cond (a p r s) (b t u) (c x y) ...)
    

    如果a 的结果为真,则评估p rs,并从cond 返回s 的值。如果a 产生错误,则尝试b,依此类推。

    cond 基本上是一个广义的or,为此您需要额外的括号:试试这个案例,否则试试那个案例,等等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-23
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-03
      • 2020-10-04
      • 2021-12-26
      相关资源
      最近更新 更多