Clojure循环/复发模式,使用不好?

时间:2015-09-18 00:11:03

标签: clojure

我正在学习Clojure,我正在使用4Clojure 作为一种资源。我可以解决很多" easy"在网站上的问题,但对我来说,在函数式编程思维中思考仍然不自然(我来自Java)。因此,我在我的大多数seq构建实现中使用循环/重复迭代模式,因为这是我以前的思考方式。

然而,当我看到更有经验的Clojure用户的答案时,他们会以更实用的方式做事。例如,in a problem about implementing the range function,我的答案如下:

(fn [start limit]
  (loop [x start y limit output '()]
    (if (< x y)
      (recur (inc x) y (conj output x))
      (reverse output))))

虽然这有效,但其他用户做了这样的事情:

(fn [x y] (take (- y x) (iterate inc x)))

我的功能更冗长,我不知道&#34;迭代&#34;功能甚至存在。但是从效率的角度来看,我的回答是否更糟?循环/重复使用比替代品更糟糕吗?我担心将来会发生很多这样的事情,因为还有许多函数,比如我不知道的迭代。

6 个答案:

答案 0 :(得分:5)

第二个变体返回一个惰性序列,这可能确实更有效,特别是如果范围很大。

另一件事是第二种解决方案更好地传达了这个想法。换句话说,它描述了意图而不是实现。与您的代码相比,它需要更少的时间来理解它,您需要通过循环体读取并在头脑中构建控制流模型。

关于新功能的发现:是的,您可能事先不知道已经定义了某些功能。在Haskell中更容易,你可以通过它的类型签名搜索函数,但是通过一些经验,你将学会识别像这样的函数式编程模式。您将编写类似第二个变体的代码,然后在标准库中查找类似takeiterate的内容。

答案 1 :(得分:3)

Clojure Cheetsheet website添加书签,并始终打开浏览器标签。

研究所有功能,特别是阅读它们链接到的示例(http://clojuredocs.org网站)。

网站http://clojure-doc.org也非常有用(是的,两个名字几乎相同但不完全相同)

答案 2 :(得分:3)

问题不应该是关于性能(取决于!),而是关于沟通:当使用loop/recur或普通递归或lazy-seq或有时甚至是reduce时,您的代码更难理解:因为读者必须先了解如何执行迭代才能理解你的计算内容。

答案 3 :(得分:1)

loop / recur是真正的Clojure,也是惯用的。这是有原因的。通常没有更好的方法。但是很多人发现,一旦习惯了它,用iterate之类的构建块构建许多函数是非常方便的。 Clojure有很好的收藏品。我开始使用真正的递归算法从头开始编写东西,然后循环/重复。就个人而言,我不会声称使用功能构建模块功能更好,但我喜欢使用它们。这是Clojure最棒的事情之一。

(是的,许多构建基块功能是懒惰的,例如formap,这些功能更为通用。懒惰可能很好,但我并不虔诚它。有时效率更高。有时它不是。有时候它很漂亮。有时候后面是痛苦。有时甚至是这样。)

答案 4 :(得分:1)

Loop和recur也不错 - 事实上,如果你看一下许多内置函数的源代码,你会发现它们就是这样做的 - 提供的函数通常是常见模式的抽象,它们可以使您的代码更容易理解。当你第一次开始时,你是如何做事的。你如何接近这似乎对我来说是正确的。您不只是编写解决方案并继续前进。您正在编写解决方案,然后查看其他人如何解决相同问题并进行比较。这是改善的正确道路。强烈建议当您找到一个看起来更优雅/高效/清晰的替代解决方案时,分析它,查看它使用的内置函数的源代码,并且事情将慢慢融合在一起。

答案 5 :(得分:1)

我好几天都想知道同样的事情,但真正的很多时间我没有看到比循环复发更好的选择。 有些工作没有完全“减少”或“映射”。当您在每次迭代时更改的缓冲区更新数据库时就是这种情况。

Loop recur非常方便,需要“非线性精确工作”。它看起来更加迫切,但如果我记得很好,Clojure的设计是实用主义的。购买,实用主义意味着选择更有效的东西。

这就是为什么在复杂的程序中,我同时使用Clojure和java代码混合。有时java对于“低级别”或迭代作业(如获取特定值等)更加清晰,而我认为Clojure函数对于大数据处理更有用(没有太多细节:全局过滤器等)。 p>

有些人说我们必须尽可能地使用Clojure,但我认为没有任何理由不使用Java。我没有编程很多,但Clojure / Java是我见过的最好的互操作,非常互补的方法。