Clojure 函数执行期间 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)))}))))))
返回的输出是如下所示的映射:
{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}
Clojure question
I have written the following function in clojure:
In the first loop it iterates a list of maps and creates a map.
Then the second loop iterates a list, matches data from the map previously created
and a vector and returns a new map. However, different runs with the same data produce
diffenet results. See below.
(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)))}))))))
The returned output is of a map like the following:
{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}
Executing the function with the same parameters sometimes yields
{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}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该函数中的所有内容都是确定性且纯粹的(除了
info
调用,这应该不重要),因此它每次都应该返回相同的内容。您没有提供任何样本输入,所以我无法反驳这个假设。该代码很难阅读,并且没有上下文我真的不明白你在做什么。但我通过几次重构检查了您的代码,试图更清楚地说明发生了什么。希望这会对正在阅读的其他人有所帮助,或者甚至让您更清楚您的问题所在。
首先
删除所有疯狂的格式和毫无意义的变量复制,并使用 seq 而不是测试 count=0
第二
解构和 if-let 而不是原始关键字查找、ifs 和 seqs:
第三
此时它是最后很清楚,我们只是迭代一个序列并构建一个结果值,因此我们可以放弃所有第一个/其余的废话,只使用
reduce
为我们遍历序列:Everything in this function is deterministic and pure (except the
info
calls, which shouldn't matter), so it should return the same thing every time. You don't provide any sample inputs, so I can't disprove this assumption.The code is hard to read, and with no context I don't really understand what you're doing. But I went through your code in several refactoring passes to try to make it clearer what's going on. Hopefully this will help someone else who is reading, or even make it clearer to you where your problem is.
First
Remove all the crazy formatting and pointless variable-copying, and use
seq
instead of testing count=0Second
Destructuring and if-let instead of primitive keyword lookups, ifs, and seqs:
Third
At this point it's finally clear that we're just iterating over a sequence and building up a result value as we go, so we can drop all the first/rest nonsense and just use
reduce
to traverse the sequence for us:如果我们不知道您的数据(函数输入)是什么样子,将很难回答您的问题,但有几点:
dd
从未在您的函数中使用,因此您可以摆脱那。let
中执行的部分分解到另一个函数中。这也将使 repl 的测试和实验变得更加容易。periods
重新映射到periods
没有任何效果,因此请摆脱它。let
中的case-details
和loop
中的periods
),这可以令人困惑,我建议不要这样做。老实说,我不明白这个 Clojure 函数如何负责为您提供不同的输出,您绝对确定输入是相同的吗?作为第一种情况下的观察,您会得到 BigDecimals 的值,所以我的猜测是,在第二种情况下,无法处理 BigDecimals 的东西与数据发生了联系。但我不明白在你提供的函数中怎么会发生这种情况。
It will be difficult to answer your question if we don't know what your data (function input) looks like, but a few points:
dd
is never used in your function, so you can get rid of that.let
out into another function. That will also make testing and experimentation at the repl easier.periods
toperiods
in the let has no effect, so get rid of that.case-details
in thelet
andperiods
in theloop
) , this can be confusing and I would advise against it.I honestly don't see how this Clojure function could be responsible for giving you different outputs, are you absolutely sure that the input is identical? As an observation in the first case you get BigDecimals for the values, so my guess is that in the second case something that couldn't handle BigDecimals was in contact with the data. But I don't see how this could have happend in the function you provide.