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呼び出して、返されたベクトルに結果を配置したい場合があることに注意してください。重要なことは、キーがマップに存在しない場合は、ベクトルにを入れてはならないということです。thatthe-otherthingnil

これはこの質問に似ていますが、出力はマップではなくベクトルであるため、を使用できません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-vector関数:cond->

(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 に答える