gpt4 book ai didi

clojure - (concat [x] y) 和 (cons x y) 有什么区别?

转载 作者:行者123 更新时间:2023-12-01 09:26:39 25 4
gpt4 key购买 nike

我被困在 Pascal's Trapezoid来自 4Clojure 站点,您需要在其中构建梯形数字的惰性序列。

我的第一个镜头是这样的:

(defn pascal [x]
(cons x
(lazy-seq
(pascal
(map +
(cons 0 x)
(conj x 0)
)))))

哪个没用:

user=> (take 5 (pascal [1 1]))
([1 1] (1 2 1) (0 2 4 2) (0 0 4 8 4) (0 0 0 8 16 8))

这样写是可行的,但是:

(defn pascal2 [x]
(cons x
(lazy-seq
(pascal2
(map +
(concat [0] x)
(concat x [0])
)))))

user=> (take 5 (pascal2 [1 1]))
([1 1] (1 2 1) (1 3 3 1) (1 4 6 4 1) (1 5 10 10 5 1))

那么,我到底做错了什么? cons/conj 和 concat 有什么区别?

最佳答案

正如其他人所说,conj 根据具体的集合类型将它接收到的元素插入到不同的位置,参见 this关于 conjcons 之间区别的更多详细信息的问题。

在您的 pascal 函数的第一个版本中,您提供了一个向量作为初始参数,因此表达式 (conj x 0) 将插入 0 在向量的末尾,用于计算系列中的第二个元素,但是 因为 map 返回一个惰性序列,当计算第三个元素时,插入发生在开头((conj (map inc '(0)) 2) ;= (2 1)),这会导致从那时起系列中的元素错误。

为了使用 consconj 方法,您必须确保使用 mapv 而不是 返回向量 map .

(defn pascal [x]
(cons x
(lazy-seq
(pascal
(mapv +
(cons 0 x)
(conj x 0))))))

(take 5 (pascal [1 1]))

;= ([1 1] [1 2 1] [1 3 3 1] [1 4 6 4 1] [1 5 10 10 5 1])

mapv 的缺点是它是急切的,因此它会计算 pascal 元素中的所有成员,而不是在您真正需要它们之前将其保留。

另一方面,当使用 concat 时,您确实要确保在末尾追加元素并且所有内容都是惰性的,但追加并不像向量那样便宜,请参阅 here了解更多信息。

不管这些因素如何,您仍然可以在这两种情况下使用 cons,因为它的作用是您在任何一种情况下都需要的(即在集合的开头插入一个元素)。

(defn pascal2 [x]
(cons x
(lazy-seq
(pascal2
(map +
(cons 0 x) ; Replaced concat with cons
(concat x [0]))))))

(take 5 (pascal2 [1 1]))

;= ([1 1] (1 2 1) (1 3 3 1) (1 4 6 4 1) (1 5 10 10 5 1))

关于clojure - (concat [x] y) 和 (cons x y) 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22282551/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com