Clojure 避免零连体可以做得更好吗?
我有一个令牌扫描器,对于我不感兴趣的字符,它只返回Clojure 避免零连体可以做得更好吗?,clojure,clojure-core,Clojure,Clojure Core,我有一个令牌扫描器,对于我不感兴趣的字符,它只返回nil。而不是conj将nil添加到我的令牌向量中,然后再将它们全部剥离出来,我只想不添加它们 我正在使用 ;; dont conjoin if value false (defn condj [v val] (cond-> v, val (conj val))) 这样做。是否有特定的运算符或更简洁的实现?我认为过度简化的方法在这里是最简洁的(它也稍微简洁一些): 我发现这更容易快速理解。唯一的缺点是v是重复的,因为它没有线程化,但这
nil
。而不是conj
将nil添加到我的令牌向量中,然后再将它们全部剥离出来,我只想不添加它们
我正在使用
;; dont conjoin if value false
(defn condj [v val]
(cond-> v, val (conj val)))
这样做。是否有特定的运算符或更简洁的实现?我认为过度简化的方法在这里是最简洁的(它也稍微简洁一些):
我发现这更容易快速理解。唯一的缺点是
v
是重复的,因为它没有线程化,但这对于这样一个简单的函数来说并不是一个很大的损失。我喜欢cond->
版本,并且经常使用它来避免在if
版本中重复。不过,不要忘记明确说明false
值。我还喜欢使用Plumatic Schema来明确说明进入和离开函数的数据形状:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require
[schema.core :as s]))
(s/defn condj :- [s/Any]
"Conjoin an item onto a vector of results if the item is not nil."
[accum :- [s/Any]
item :- s/Any]
(cond-> accum
(not (nil? item)) (conj item)))
(dotest
(let [result (-> []
(condj :a)
(condj :2)
(condj false)
(condj "four")
(condj nil)
(condj "last"))]
; nil is filtered but false is retained
(is= result [:a :2 false "four" "last"])))
您可能还对另一个版本感兴趣,使用:
对于更复杂的表单,使用占位符符号it
可以明确值的线程位置。我也喜欢方便的函数not nil?
和append
,因为它们也可以使代码的意图更加清晰。我相信您可以使用传感器来实现这一点。他们被解释了。我们的还原函数是conj
,我们构造了一个传感器(移除nil?
,将此函数转换为忽略nil
:
(def condj ((remove nil?) conj))
(def condj ((filter some?) conj))
请注意,remove
与filter
相反。我们还可以使用(filter some?
)实现condj
,这是一个对除nil
以外的任何值都适用的函数:
(def condj ((remove nil?) conj))
(def condj ((filter some?) conj))
这似乎有效:
user=> (condj [3 4 5] 9)
[3 4 5 9]
user=> (condj [3 4 5] nil)
[3 4 5]
user=> (condj [3 4 5] false)
[3 4 5 false]
考虑在中使用
而不是conj
:
(into [1 2 3] nil) ;=> [1 2 3]
(into [1 2 3] [4]) ;=> [1 2 3 4]
注意:缺点是您必须按顺序返回结果,这会增加一点开销。但是,如果您忘记执行此操作,则会出现错误,当您想要附加多个项目时,可以很容易地扩展逻辑,代码很容易理解,并且不需要创建任何自定义函数。很好,传感器可以进一步简化为(过滤一些?
或(删除零?)
。我不知道删除
函数,但这样一个函数的存在非常有意义。我将我的答案编辑为使用删除
而不是过滤器
,谢谢!