【问题标题】:vectors vs lists with immutable data in ClojureClojure 中的向量与具有不可变数据的列表
【发布时间】:2019-06-20 20:19:10
【问题描述】:

我已经写了两次相同的函数,每次都分别使用一个列表和一个向量。该函数找到一个元素并返回集合中的下一个元素,如果找到的元素位于末尾,则返回。如果找不到元素,则返回nil

列出版本

(def syms '(\< \^ \> \v))

(defn next-elem- [coll elem]
  (loop [coll-rest coll]
    (cond
      (empty? coll-rest) nil
      (= (first coll-rest) elem) (nth coll-rest 1 (first coll))
      :else (recur (rest coll-rest)))))

(defn rotate-left [sym]
  (next-elem- syms sym))

矢量版

(def syms [\< \^ \> \v])

(defn next-index- [coll i]
  (let [elem-count (count coll)]
    (cond
      (or (< i 0) (> i elem-count)) -1
      (= i (dec elem-count)) 0
      :else (inc i))))

(defn rotate-left [sym]
  (let [i (.indexOf syms sym)]
    (get syms (next-index- syms i) nil)))

测试

(assert (= \< (rotate-left \v)))
(assert (= nil (rotate-left \o)))

哪个版本更好?我读过列表通常在函数式编程中是首选,至少在 F# 向量(那里的数组)中是可变的,这不是我需要的。处理索引也感觉很尴尬,但作为非函数式程序员更容易理解。

PS:这是我编写的第一个函数式程序之一,所以它可能不是最优的。 PPS:我是否正确使用了反斜杠,还是应该使用其他东西来代替它?

【问题讨论】:

  • Clojure 向量是不可变的。另请注意,clojure 列表实际上是引擎盖下的 64 元树。至于列表比向量更好,这取决于。
  • 列表不是单链表吗?
  • @Carcigenicate 我明白了,很有趣。不过,之前的链接提到列表相当于 Java LinkedList
  • Clojure 列表确实是单链表。根本不涉及树木;它们非常简单。向量被实现为分支因子为 32 的树。

标签: types clojure functional-programming containers


【解决方案1】:

next-elem- 的第一个版本更好,因为它适用于任何序列。第二个版本依赖序列来进行高效的索引访问,这真的很容易意外失败并得到一个低性能的代码。

建议:将rest 更改为next。不推荐使用 Rest,在所有情况下,next 都会更好。

同时避免使用列表。它们是非常具体的数据结构,很少需要。每当您需要线性序列时,请先考虑向量。

您的代码的功能版本:

(defn next-elem- [coll elem]
  (->> (concat coll [(first coll)])
       (drop-while #(not= % elem))
       (second)))

【讨论】:

  • 感谢您的帮助!这个很酷的实现证明了我的想法仍然很传统
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-21
  • 2014-02-18
  • 2011-03-09
相关资源
最近更新 更多