【问题标题】:Converting To loop ... recur recursion转换为循环...递归递归
【发布时间】:2011-09-14 18:04:16
【问题描述】:

据我了解,在 Clojure 中递归而不使用循环 .. recur 语法对于短序列可能不是问题。但是,使用 loop .. recur 语法是编写递归函数的首选方法。所以,我想从首选方法开始。

但是,我一直在努力转换这个函数 [edit],它返回一个序列的骨架(没有它的值的序列结构)

(defn skl
  [tree]
  (map skl (filter seq? tree)))

用这些数据测试过

(def test_data1 '(1 (2 3) ( ) (( )) :a))
(def test_data2 '(1 2 (3 4) (5 ( 6 7 8))))

循环 .. 重复语法。任何想法或指向示例的指针将不胜感激。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    循环和递归是简单迭代的一种转换。然而,下降到树中本质上是递归的。您必须手动维护堆栈才能将其转换为单个迭代。因此,您的代码没有“简单”转换。

    【讨论】:

    • 谢谢。我知道 Clojure.zip,但想尝试通过自己滚动来提取骨架。这个例子来自宾夕法尼亚大学的一些研究生计算机科学练习。你的回答至少告诉我这不是一个简单的问题要解决。谢谢。
    【解决方案2】:

    您可能想研究一下 zipper 库,该库允许良好的结构化树编辑,尽管它可能不如您原来的优雅。我几乎从不需要使用循环...重复。几乎总是有一个高阶函数可以以相同或更好的效率更优雅地解决问题。

    map 替换为loop ... recur 会使代码更加冗长且不清晰。您也会失去分块序列的好处。

    【讨论】:

    • 谢谢。您指的是 Clojure.zip,对吗?我知道它,会使用它,并且想在没有它的情况下做这个练习。
    • Trampoline 也是一个有趣的功能,除了 loop-recur 之外,还需要了解,虽然这里不直接适用。
    【解决方案3】:

    查看 clojure.walk 源代码。它是一个对所有 Clojure 嵌套数据结构(不包括有序映射)进行(批量)操作的库。里面有一些非常强大但看似简单的代码,通过本地定义的匿名函数使用递归而不使用循环/递归。

    其中的大部分函数都基于 postwalk 和 prewalk 函数,而这两个函数又都基于 walk 函数。通过源代码和(prewalk-demo form)和(postwalk-demo form),您可以很好地了解所采取的递归步骤。

    我不知道这是否可以帮助您解决问题。我目前正在尝试在同一个问题域中做一些事情:创建一个函数以将嵌套映射和向量“展平”为从根到叶的所有路径序列,每个路径都是以'结尾的键和/或索引序列叶的价值。

    这个库似乎使得在整个结构中递归地编辑值变得非常简单。但是,我仍然不知道如何使用它来在功能上跟踪我的“路径”所需的迭代之间的累积数据,并且可能还有你的“骨架”问题。

    【讨论】:

      猜你喜欢
      • 2020-09-05
      • 1970-01-01
      • 2019-05-11
      • 2013-11-29
      • 1970-01-01
      • 1970-01-01
      • 2013-05-31
      • 1970-01-01
      相关资源
      最近更新 更多