Я написал одну и ту же функцию дважды, каждый из которых использовал список и вектор соответственно.Функция находит элемент и возвращает следующий в коллекции и оборачивает, если найденный элемент находится в конце.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: Правильно ли я использую обратную косую черту или мне нужно что-то другое вместо нее?