我如何有条件地连接到Clojure向量

sta*_*and 5 clojure

是否有更干净的方法在Clojure中执行以下操作?

(defn this [x] (* 2 x))
(defn that [x] (inc x))
(defn the-other [x] (-> x this that))

(defn make-vector [thing]
  (let [base (vector (this (:a thing))
                     (that (:b thing)))]
    (if-let [optional (:c thing)]
      (conj base (the-other optional))
      base)))

(make-vector {:a 1, :b 2}) ;=> [2 3]
(make-vector {:a 1, :b 2, :c 3}) ;=> [2 3 7]
Run Code Online (Sandbox Code Playgroud)

我所说的“更清洁”更接近于此:

(defn non-working-make-vector [thing]
  (vector (this (:a thing))
          (that (:b thing))
          (if (:c thing) (the-other (:c thing)))))

(non-working-make-vector {:a 1, :b 2} ;=> [2 3 nil]  no nil, please!
(non-working-make-vector {:a 1, :b 2, :c 3} ;=> [2 3 7]
Run Code Online (Sandbox Code Playgroud)

请注意,我可能要调用一些任意的功能(例如thisthatthe-other在任何键)thing,并将结果存放在返回的矢量。重要的是,如果键在地图中不存在,则不应nil在向量中放置a 。

这类似于这个问题,但是输出是向量而不是地图,所以我不能使用merge

mob*_*yte 2

(defn this [x] (* 2 x))
(defn that [x] (inc x))
(defn the-other [x] (-> x this that))

(def k-f-map {:a this
              :b that
              :c the-other})

(def m1 {:a 1 :b 2})
(def m2 {:a 1 :b 2 :c 3})

(defn make-vector [k-f-map m]
  (reduce (fn [res [fk fv]]
            (if (fk m)
              (conj res (fv (fk m)))
              res))
          [] k-f-map))

(make-vector k-f-map m1)
-> [2 3]

(make-vector k-f-map m2)
-> [2 3 7]
Run Code Online (Sandbox Code Playgroud)