recursion - 由于 zipper 和 HOF,递归是一种气味(在惯用的 Clojure 中)吗?

标签 recursion clojure higher-order-functions idioms zipper

经典书籍The Little Lisper ( The Little Schemer ) 建立在两大理念之上

  • 您可以以递归方式(而不是使用循环)解决大多数问题(假设您有尾调用优化)
  • Lisp 很棒,因为它本身很容易实现。

  • 现在人们可能认为这适用于所有 Lispy 语言(包括 Clojure)。问题是,这本书是它那个时代(1989 年)的人工制品,可能早于 Functional ProgrammingHigher Order Functions (HOF)就是我们今天所拥有的。(或者至少被认为对本科生来说是可口的)。

    递归的好处(至少部分)是易于遍历嵌套数据结构,如 ('a 'b ('c ('d 'e))) .

    对于 example :
    (def leftmost
      (fn [l]
        (println "(leftmost " l)
        (println (non-atom? l))
        (cond
          (null? l) '()
          (non-atom? (first l)) (leftmost (first l))
          true (first l))))
    

    现在与 Functional Zippers - 我们有一种遍历嵌套数据结构的非递归方法,并且可以像遍历任何惰性数据结构一样遍历它们。对于 example :
    (defn map-zipper [m]
      (zip/zipper 
        (fn [x] (or (map? x) (map? (nth x 1))))
        (fn [x] (seq (if (map? x) x (nth x 1))))
        (fn [x children] 
          (if (map? x) 
            (into {} children) 
            (assoc x 1 (into {} children))))
        m))
    
    (def m {:a 3 :b {:x true :y false} :c 4})
    
    (-> (map-zipper m) zip/down zip/right zip/node)
    ;;=> [:b {:y false, :x true}]
    

    现在看来,您可以使用以下任一方法解决任何嵌套列表遍历问题:
  • zipper如上,或
  • zipper遍历结构并返回一组键,让您可以使用 assoc 修改结构.

  • 假设:
  • 我当然假设数据结构是固定大小的,并且在遍历之前完全知道
  • 我不包括流数据源场景。

  • 我的问题是:由于 zipper 和 HOF,递归是一种气味(在惯用的 Clojure 中)吗?

    最佳答案

    我会说,是的,如果您正在进行手动递归,您至少应该重新考虑是否需要。但我不会说 zipper 与此有任何关系。我对 zipper 的经验是,它们具有理论用途,对 Clojure 新手来说非常令人兴奋,但一旦掌握了窍门,就没有什么实际值(value)了,因为它们有用的情况非常罕见。

    真的是因为高阶函数已经为你实现了常见的递归模式,手动递归并不常见。但是,您绝对不应该使用手动递归:这只是一个警告信号,表明您可能可以做其他事情。在我使用 Clojure 的四年中,我什至不记得我实际上需要一个 zipper 的情况,但我最终经常使用递归。

    关于recursion - 由于 zipper 和 HOF,递归是一种气味(在惯用的 Clojure 中)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29059027/

    相关文章:

    javascript - 输出JSON的javascript中的递归函数

    clojure - 在Leiningen项目中保持依赖版本最新

    swift - 为什么我的过滤器版本与 Swifts 的表现如此不同?

    python - 分布的迭代排列

    python - 带 yield 的递归函数不返回任何东西

    c - 在C中通过引用递归传递字符串

    clojure - 为什么 Clojure 中的向量没有实现 dissoc?

    clojure - 从 go block 中获取信息

    Scala ActionListener/匿名函数类型不匹配

    javascript - 如何记录javascript高阶函数?