将元素放在集合的尾部

Mic*_*ent 52 collections clojure

我发现自己做了很多:

(concat coll [e]) 其中coll是一个集合,而ea是一个单独的元素.

在Clojure中有没有这样做的功能?我知道conj对矢量做的最好,但我不知道前面会使用哪种coll.例如,它可以是矢量,列表或排序集.

ama*_*loy 53

某些类型的集合可以廉价地添加到前面(列表,seq),而其他类型的集合可以廉价地添加到后面(向量,队列,有点类型lazy-seqs).如果可能的话,你应该安排使用其中一种类型(向量是最常见的)而不是使用concat,而只需要使用它:(conj [1 2 3] 4)收益率[1 2 3 4],而(conj '(1 2 3) 4)收益率(4 1 2 3).

  • `(concat coll [e])`:P (13认同)
  • 两年后编辑:我不会写这个功能. (13认同)
  • @Jon如果我需要在集合的末尾添加项目,我会:(a)安排事情,以便我可以使用向量或懒惰地构建序列,或(b)通过强迫自己强迫自己看起来很难看每次都写``(concat coll [x])`而不是呼唤一些无辜的功能来完成这项肮脏的工作. (3认同)

Lau*_*tit 14

concat不会在集合的尾部添加元素,也不会连接两个集合.

concat返回由两个其他seq的串联组成的seq.对于concat的返回类型,可以推断出可以推断seq的集合的原始类型.

现在,Clojure的集合都为了写出高效的代码不同的属性必须知道,这就是为什么没有在核心提供的通用功能来连接任何类型的集合在一起.相反,列表和向量确实具有"自然插入位置",它们知道并且做出适合于该类型集合的内容.


Mar*_*ars 6

这是@ amalloy答案的一个非常小的附录,以解决OP对一个函数的要求,该函数总是增加任何类型集合的尾部.这是另一种选择(concat coll [x]).只需创建原始集合的矢量版本:

(defn conj*
  [s x]
  (conj (vec s) x))
Run Code Online (Sandbox Code Playgroud)

注意事项:

如果你以一个懒惰的序列开始,你现在已经破坏了懒惰 - 即输出不是懒惰的.根据您的需要,这可能是好事还是坏事.

创建矢量需要一些成本.如果你需要经常调用这个函数,并且你发现(例如通过使用Criterium进行基准测试)这个成本对于你的目的很重要,那么请按照其他答案的建议尝试首先使用向量.

  • 在这种情况下,惰性的破坏并不是真正的成本。追加到列表的末尾意味着列表将被完全实现。 (2认同)

sem*_*ros 5

要充分利用amalloy和Laurent Petit所说的话,请使用该conj函数

Clojure提供的出色抽象之一是Sequence API,其中包括该conj函数。如果可能的话,您的代码应尽可能与集合类型无关,而应使用seq API处理集合的操作,并仅在需要特定时才选择特定的集合类型。

如果矢量是很好的匹配,那么可以,conj将在最后添加项目。如果使用列表代替,那么conj会将东西添加到集合的前面。但是,如果您随后使用标准的seq API函数从集合的“顶部”(向量的背面,列表的正面)提取项目,则使用哪种实现都无关紧要,因为它将始终使用具有最佳性能并因此添加和删除项目的项目将保持一致。

  • 对于元组顺序很重要。在 Lisp 方言计划中,“append”是内置的。我认为期望语言具有这样的功能是完全合理的。 (3认同)
  • @Michiel Borkent毫不费力地进行“我是否使用了最惯用的语言构造”检查。没有更多细节(例如为什么需要结尾),很难进一步提供帮助。 (2认同)