递归地运行Clojure中的向量

时间:2014-04-17 00:36:10

标签: recursion clojure

我刚刚开始玩Clojure。

如何浏览项目向量?

我天真的递归函数会有一个像经典地图的形式,例如。

(defn map [f xs] (
  (if (= xs [])
      []
      (cons (f (first xs)) (map f (rest xs))
  )
))

事情是我在网上找不到这种代码的任何例子。我找到了很多使用内置序列遍历函数的例子,例如for,map和loop。但没有人在做原始的递归版本。

那是因为你不应该在Clojure中做这种事情吗? (例如,因为它使用的是没有尾调用优化的低级Java原语?)?

2 个答案:

答案 0 :(得分:2)

当你说“通过矢量”时,这是非常模糊的;因为Clojure是一个lisp,因此专门用于序列分析和操作,使用这种语言的美妙之处在于你不会用“通过向量然后对每个元素做一些事情”的术语来思考,而是你更习惯地说“将其从矢量中拉出来”或“将此矢量转换为X”或“我希望此矢量给我X”。

正是由于lisp语言中的这种类型的观点,你才会看到很多例子和生产代码,它们不仅仅通过向量循环/重复,而是以一种简短的惯用方式专门追求所需的东西。使用reduce map filter for into等其他简单函数可以让您优雅地移动一个序列,例如矢量而同时用内容做你想做的事。在大多数其他语言中,这将至少有两个不同的部分:循环,然后是实际所需的逻辑。

你经常会发现,如果你想到使用C,C ++,Java等语言所带来的更为命令性思想的序列,那么你的代码比你原来的代码要长4倍(至少)首先考虑你的计划采用更具功能性的方法。

答案 1 :(得分:1)

Clojure仅使用尾递归重新使用堆栈帧,并且仅在使用显式recur 调用时。其他一切都将是堆栈消耗。上面的地图示例不是尾递归的,因为缺点发生在递归调用之后,因此它不能以任何语言进行TCO。如果您将其切换为使用延续传递样式并使用显式调用recur而不是map那么您应该好好去。