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)))}))))))
返回的输出是如下地图:
{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}
执行具有相同参数的函数有时会产生
{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}
答案 0 :(得分: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)))))
解构和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)))))
此时我们最终清楚地知道我们只是迭代一个序列并构建一个结果值,因此我们可以删除所有的第一个/其余的废话并只使用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)))
答案 1 :(得分:1)
如果我们不知道您的数据(函数输入)是什么样子,那么很难回答您的问题,但有几点:
dd
从未在您的函数中使用,因此您可以摆脱它。let
中所做的部分分解为另一个函数。这也将使repl的测试和实验更容易。periods
到periods
没有任何效果,所以摆脱它。case-details
中的let
和periods
中的loop
),这可能令人困惑,我会建议不要这样做。 老实说,我不知道这个Clojure函数如何为你提供不同的输出,你绝对确定输入是相同的吗?作为第一种情况的观察,你得到值的BigDecimals,所以我的猜测是,在第二种情况下,无法处理BigDecimals的东西与数据接触。但我不知道你在提供的功能中会发生这种情况。