2

我正在使用 Clojure进行一些 Lisp练习。我正在尝试在不利用向量和某些 Clojure 函数的情况下进行这些练习。

这个功能

(defn rev-seq
    [s1]
    (concat (pop s1) (list (peek s1))))

将列表的第一个元素放在末尾。我想多次调用这个函数来反转列表(不调用 Clojure 的reverse函数)。

我不确定用什么代替它。我已经尝试过映射、应用和重复,但没有成功。我宁愿有一种不同的方式来思考这个问题,而不是一个直接的答案,但我不是要求讨论。

4

2 回答 2

4

首先,如果您想处理一般序列,我认为您需要将 rev-seq 转换为使用first/rest而不是peek/ pop- 至少在 Clojure 1.4 中peek/pop似乎需要 PersistentStack:

(defn rev-seq
  [s1]
  (concat (rest s1) (list (first s1))))

那么您可能应该注意到,重复应用此函数将“循环”列表而不是反转它。如果您使用以下方法查看少量应用程序的结果,您会看到iterate

(def s '(1 2 3 4 5 6 7 8 9))

(nth (iterate rev-seq s) 3)
=> (4 5 6 7 8 9 1 2 3)

一个可行的选择是使用递归函数进行反转:

(defn reverse-seq [s]
  (concat (reverse (next s)) (list (first s))))

(reverse-seq s)
=> (9 8 7 6 5 4 3 2 1)

或者,您可以使用 clojure.core 中的技术进行反向操作:

(defn reverse-seq [s]
  (reduce conj () s))

(reverse-seq s)
=> (9 8 7 6 5 4 3 2 1)

希望这能给你一些想法!

于 2012-10-06T00:45:21.890 回答
1

递归很强大!我将 解决方案翻译 成 Clojure。

(defn- inverte-aux
  [lista resto]
  (if lista
    (recur (next lista) (cons (first lista) resto))
    resto))

(defn inverte
  [lista]
  (inverte-aux lista nil))

user> (inverte [4 3 2 1 3])
(3 1 2 3 4)
于 2012-10-06T06:59:37.800 回答