在下面的代码中,我想使用(conj listvalue countString)在列表中添加一个元素
(defn unique-character [parms]
(let [split (#(str/split % #"") parms)
countString (count split)
listvalue #{}]
(dbg (doseq [countString split]
(println countString)
(conj listvalue countString)
(println listvalue)
))listvalue))
(unique-character "Leeeeeerrroyyy")
Output to be - Leroy
但是我得到一个空列表作为输出结果
有人可以帮我为什么不将字符添加到列表中吗,也许这不是很好的代码,但是我想了解conj在doseq中的表现
最重要的是,conj
将不会更改输入序列,而是将返回输入序列的新版本,并在最后添加元素:
(def x [:a :b :c])
(conj x :d)
x
;; => [:a :b :c]
(def y (conj x :d))
y
;; => [:a :b :c :d]
这是为什么要在命令式语言及其标准库上使用Clojure及其标准库的许多重要原因之一:让函数返回集合的新版本而不是对其进行修改,会使通过程序的数据流更易于推理,并使得并发也更容易。
你也不需要使用来分割字符串split
,因为可以直接将其视为序列。确实doseq
会像其他语言中的for-each-loop一样逐个元素地循环序列,以便在每次迭代中都产生一些副作用。但是conj
除了返回输入序列的新版本之外,没有副作用。
在这种情况下,我们将使用reduce
,就像doseq
遍历一个序列一样。但是它将loop-state
在下面的代码中跟踪一个值(),该值保存循环的状态并在最后返回。这是unique-characters
所问问题的功能的重写版本:
(defn unique-characters [parms]
(reduce (fn [loop-state input-character]
(conj loop-state input-character)) ;; <-- Return next loop state
#{} ;; <-- Initial loop state (that is "listvalue")
parms ;; <-- The input string (sequence of characters)
))
(unique-characters "Leeeeeerrroyyy")
;; => #{\e \L \o \r \y}
这将返回一组输入序列的字符。从问题的措辞来看,这可能不是你想要的结果。这是一个修改后的版本,它最多将每个字符添加到输出序列一次并生成一个字符串。
(defn unique-characters-2 [parms]
(apply str ;; <-- Build a string from the value returned by reduce below
(reduce (fn [loop-state input-character]
(if (some #(= input-character %) loop-state)
loop-state
(conj loop-state input-character)))
[] ;; <-- Initial loop state
parms ;; <-- Input string (sequence of characters)
)))
(unique-characters-2 "Leeeeeerrroyyy")
;; => "Leroy"
是否有任何链接说在减少和剂量之间使用哪个?我总是对可以在Clojure中使用哪个功能感到困惑
在我了解它们的作用之前,我将尝试使用doseq中的任何一个并减少一些小示例。它们都基于循环,因此您可能需要先研究循环。