如何多次将函数应用于序列

时间:2012-10-05 22:44:20

标签: clojure

我正在使用Clojure处理一些Lisp exercises。我试图在不利用向量和一些Clojure函数的情况下完成这些练习。

此功能

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

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

我不确定在它的位置使用什么。我已经尝试过地图,应用和重复但没有成功。我宁愿有办法对此进行不同的思考,而不是直接回答,但我不是要求讨论。

2 个答案:

答案 0 :(得分:4)

首先,如果您想处理一般序列,我认为您需要将rev-seq转换为使用first / rest而不是peek / pop - 在Clojure 1.4中的leas 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)

希望这会给你一些想法!

答案 1 :(得分:1)

递归很强大! 我翻译了 the solution 进入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)