Clojure: 如何将cons转换为list

3

(cons 1 (list 2 3))返回一个clojure.lang.cons。我该如何将其转换为clojure.lang.PersistentList


8
首先,这种转换的目的是什么?从Clojure的角度来看,它们是类似的序列。你的目标是什么?如果你需要在某种条件语句中使用它,只需使用seq?而不是list?:它适用于两者。 - leetwinski
4个回答

13

不要调用cons并尝试转换结果,而是使用conj

(conj (list 2 3) 1)
=> (1 2 3)

(type (conj (list 2 3) 1))
=> clojure.lang.PersistentList

6
Clojure: 如何将cons转换为list
不要这样做!
Clojure是建立在可扩展抽象之上的。其中最重要的之一是序列
我想不出任何理由为什么你想要将cons转换为list或者反过来。它们都是序列,没有太大的区别。你可以用一个做的事情,同样也可以用另一个做。
上面的内容是对Leetwinski在问题中的评论的进一步阐述。

3
我大体上同意你的答案(我认为这是此处最佳答案),但肯定有人会因为某些原因想要使用列表而不是序列:例如,列表知道它们的计数,而对于一般序列,计数函数可能需要任意长的时间。然而,对于那些不知道如何将序列转换为列表的人来说,很难想象他们实际上需要列表。 - amalloy

3

您可以将返回的序列内容应用于 list 函数:

(apply list (cons 1 (list 2 3)))
=> (1 2 3)
(type *1)
=> clojure.lang.PersistentList

这个解决方案不是符合Clojure代码习惯的。在这种情况下,你应该使用conj函数。 - Kungi

-2

最简单的方法是将其转换为向量。在Clojure中,这种数据类型非常好用。实际上,在Clojure编程中,大部分数据都保存在向量或映射中,而列表则用于“代码即数据”(宏系统)。

对于您的情况,解决方案如下:

user=> (vec (cons 1 (list 2 3)))
[1 2 3]

我不知道确切的情况,你需要一个列表而不是向量或序列。因为大多数函数操作的是序列,而不是严格的集合类型。我相信cons类型也可以工作。

如果你真的需要一个列表,你可以使用into函数来转换集合的类型。但请记住,当处理列表时,顺序会相反:

user=> (into '() (cons 1 (list 2 3)))
(3 2 1)

所以你需要先反转输入数据:

user=> (into '() (reverse (cons 1 (list 2 3))))
(1 2 3)

user=> (type (into '() (reverse (cons 1 (list 2 3)))))
clojure.lang.PersistentList

2
the quote is optional before empty list literal : (= () '()) - leetwinski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接