【发布时间】: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