如何使用固定键和条件值返回clojure贴图?

sta*_*and 6 idiomatic clojure

我有一个返回地图的函数.键是静态的,但值是有条件的.像这样:

(defn map-returning-function [x y]
  {:a (if (some-test-fn x)  "one value" "other value"
   :b (if (some-test-fn x)   15         25
   :c (if (different-test y) :one       :two})
Run Code Online (Sandbox Code Playgroud)

是否有一些更优雅的方法来实现这一点,而无需if为每个值编写测试?我能想到的另一种方式是

(defn another-map-returning-function [x y]
  (if (some-test-fn x)
    {:a "one value",  :b 15, :c (if (different-test y) :one :two)}
    {:a "other value" :b 25, :c (if (different-test y) :one :two)}))
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎并不好,因为它重复了条件的每个分支的键名,并重复了函数调用different-test.天堂禁止我需要一个cond而不是一个if.

kot*_*rak 5

人们可以想到的另一种变化是使用merge.一个案例用作默认值,根据函数参数进行修改.通过这种方式,您可以轻松地对测试进行分组,并在必要时添加一些注释.

(defn map-returning-function
  [x y]
  (merge {:a "other value"
          :b 25
          :c :two}
         (when (some-test-fn x)
           {:a "one value"
            :b 15})
         (when (different-test y)
           {:c :one})))
Run Code Online (Sandbox Code Playgroud)

或者反过来,取决于您认为是默认值.

(defn map-returning-function
  [x y]
  (merge {:a "one value"
          :b 15
          :c :one}
         (when-not (some-test-fn x)
           {:a "other value"
            :b 25})
         (when-not (different-test y)
           {:c :two})))
Run Code Online (Sandbox Code Playgroud)


Kon*_*rus 4

这个怎么样:

(let [test-x (some-test x) test-y (some-test y)] 
  (conj 
    (if test-x {:a "one value" :b 15} {:a "other value" :b 25}) 
    (if test-y {:c :one} {:c :two})))
Run Code Online (Sandbox Code Playgroud)

条件在一个地方执行一次,然后在另一个地方使用。不过取决于上下文和个人喜好。更像你的例子的东西可能更干净:

(let [test-x (some-test x) test-y (some-test y)] 
  {:a (if test-x "one value" "other value")
   :b (if test-x 15 25)
   :c (if test-y :one :two)})
Run Code Online (Sandbox Code Playgroud)