5

在 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]

通过“更清洁”,我的意思是更接近于这个:

(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]

请注意,我可能想在其中的任何键上调用一些任意函数(例如this, that, the-otherthing并将结果放入返回的向量中。重要的是,如果地图中不存在密钥,则不应将 anil放入向量中。

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

4

3 回答 3

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]
于 2012-12-15T16:52:21.437 回答
1
;;; replace [:a :b :c] with a vector of arbitrary functions
;;; of your choice, or perhaps accept a seqable of functions
;;; as an extra argument
(defn make-vector [thing]
  (into [] (keep #(% thing) [:a :b :c])))

;;; from the REPL:
(make-vector {:a 1 :b 2})
; => [1 2]
(make-vector {:a 1 :b 2 :c 3})
; => [1 2 3]

请注意,keep仅抛出nil; false将包含在输出中。

于 2012-12-15T02:48:56.810 回答
0

或使用cond->

make-vectorcond->版本中的功能:

(defn make-vector [thing]
  (cond-> [(this (:a thing))
           (that (:b thing))]
    (:c thing) (conj (the-other (:c thing)))))

您可以有更多条件或将 :a 和 :b 更改为可选的。

于 2021-07-06T23:28:36.120 回答