Clojure Inconsistent在执行函数期间导致clojure

kos*_*tas 0 clojure

Clojure问题

我在clojure中编写了以下函数:在第一个循环中,它迭代一个映射列表并创建一个映射.然后第二个循环迭代一个列表,匹配先前创建的映射数据和一个向量并返回一个新映射.但是,使用相同数据的不同运行会产生不同的结果.见下文.

(defn resolve-case-per-period
  "Constructs a map by matching data existing in input parameter vectors"
  [dd case-details periods]
  (let [cases ((fn [in] 
                 (loop [case-details in, result-map {}] 
                   (if (= (count case-details) 0) 
                     result-map 
                     (recur (rest case-details) 
                            (assoc result-map
                              (:priority (first case-details)) 
                              (:caseid (first case-details)))))))
               case-details)
         periods periods]
    (info "Mapping cases to periods step 1 completed " cases)
    (loop [periods periods, result-map {}]
      (if (= (count periods) 0)
        result-map
        (recur (rest periods) 
               (conj result-map
                     { (str (:period (first periods)))
                       (get cases (:priority (first periods)))}))))))
Run Code Online (Sandbox Code Playgroud)

返回的输出是如下地图:

{31-10-10 20 10020101030122036M, 31-10-10 10 10020101030122036M, 31-10-10 21 10020101030122036M, 30-10-10 21 10020101030200157M, 31-10-10 00 10020101030122036M, 31-10-10 11 10020101030122036M, 31-10-10 22 10020101031112152M, 30-10-10 22 10020101030122036M, 31-10-10 01 10020101030122036M, 31-10-10 12 10020101030122036M, 30-10-10 23 10020101030122036M, 31-10-10 02 10020101030122036M, 31-10-10 13 10020101030122036M, 31-10-10 03 10020101030122036M, 31-10-10 14 10020101030122036M, 31-10-10 04 10020101030122036M, 31-10-10 15 10020101030122036M, 31-10-10 05 10020101030122036M, 31-10-10 16 10020101030122036M, 31-10-10 06 10020101030122036M, 31-10-10 17 10020101030122036M, 31-10-10 07 10020101030122036M, 31-10-10 18 10020101030122036M, 31-10-10 08 10020101030122036M, 31-10-10 19 10020101030122036M, 31-10-10 09 10020101030122036M}
Run Code Online (Sandbox Code Playgroud)

执行具有相同参数的函数有时会产生

{31-10-10 20 nil, 31-10-10 10 nil, 31-10-10 21 nil, 30-10-10 21 nil, 31-10-10 00 nil, 31-10-10 11 nil, 31-10-10 22 nil, 30-10-10 22 nil, 31-10-10 01 nil, 31-10-10 12 nil, 30-10-10 23 nil, 31-10-10 02 nil, 31-10-10 13 nil, 31-10-10 03 nil, 31-10-10 14 nil, 31-10-10 04 nil, 31-10-10 15 nil, 31-10-10 05 nil, 31-10-10 16 nil, 31-10-10 06 nil, 31-10-10 17 nil, 31-10-10 07 nil, 31-10-10 18 nil, 31-10-10 08 nil, 31-10-10 19 nil, 31-10-10 09 nil}
Run Code Online (Sandbox Code Playgroud)

ama*_*loy 7

这个函数中的所有东西都是确定性的和纯粹的(除了info调用,这应该不重要),所以每次都应该返回相同的东西.您没有提供任何样本输入,因此我无法反驳这一假设.

代码很难阅读,没有上下文我真的不明白你在做什么.但是我在几个重构过程中经历了你的代码,试图让它更清楚地发生了什么.希望这可以帮助正在阅读的其他人,甚至可以让你在问题所在的地方更清楚.

第一

删除所有疯狂的格式和无意义的变量复制,并使用seq而不是测试count = 0

(defn resolve-case-per-period
  "Constructs a map by matching data existing in input parameter vectors"
  [dd case-details periods]
  (let [cases (loop [case-details case-details, result-map {}] 
                (if (seq case-details)
                  (recur (rest case-details)
                         (assoc result-map 
                           (:priority (first case-details))
                           (:caseid (first case-details)))) 
                  result-map))]
    (info "Mapping cases to periods step 1 completed " cases)
    (loop [periods periods, result-map {}]
      (if (seq periods)
        (recur (rest periods) 
               (assoc result-map
                 (str (:period (first periods)))
                 (get cases (:priority (first periods)))))
        (do (info "Mapping cases to periods step 2 completed " result-map)
            result-map)))))
Run Code Online (Sandbox Code Playgroud)

第二

解构和if-let而不是原始关键字查找,ifs和seqs:

(defn resolve-case-per-period
  "Constructs a map by matching data existing in input parameter vectors"
  [dd case-details periods]
  (let [cases (loop [case-details case-details, result-map {}] 
                (if-let [[{:keys [priority case-id]} & more] (seq case-details)]
                  (recur more
                         (assoc result-map priority caseid)) 
                  result-map))]
    (info "Mapping cases to periods step 1 completed " cases)
    (loop [periods periods, result-map {}]
      (if-let [[{:keys [period priority]} & more] (seq periods)]
        (recur more
               (assoc result-map
                 (str period)
                 (get cases priority)))
        (do (info "Mapping cases to periods step 2 completed " result-map)
            result-map)))))
Run Code Online (Sandbox Code Playgroud)

第三

在这一点上,我们最终清楚地看到我们只是迭代一个序列并构建一个结果值,所以我们可以删除所有的第一个/其余的废话并且只是reduce用来遍历我们的序列:

(defn resolve-case-per-period
  "Constructs a map by matching data existing in input parameter vectors"
  [dd case-details periods]
  (let [cases (reduce (fn [result-map {:keys [priority case-id]}]
                        (assoc result-map priority caseid))
                      {}, case-details)]
    (info "Mapping cases to periods step 1 completed " cases)
    (reduce (fn [result-map {:keys [period priority]}]
              (assoc result-map
                (str period)
                (get cases priority)))
            {}, periods)))
Run Code Online (Sandbox Code Playgroud)