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]

注意:缺点是您必须按顺序返回结果,这会增加一点开销。但是,如果您忘记执行此操作,则会出现错误,当您想要附加多个项目时,可以很容易地扩展逻辑,代码很容易理解,并且不需要创建任何自定义函数。

很好,传感器可以进一步简化为
(过滤一些?
(删除零?)
。我不知道
删除
函数,但这样一个函数的存在非常有意义。我将我的答案编辑为使用
删除
而不是
过滤器
,谢谢!