【问题标题】:Does the order of function calls inside a Clojure map guarantee runtime order processing?Clojure 映射中的函数调用顺序是否保证运行时顺序处理?
【发布时间】:2021-09-01 20:32:19
【问题描述】:

我正在开发以下功能:

(defn process-request [request]
  (if (not (db/empty?))
    {:person (db/get-person!) :violations (:violations (process-violations request))}
    {:person {} :violations ["no-person"]}))

我需要 process-violations 函数仅在 db 不为空时才被调用。这就是为什么它在 if 块中。

但是,我还需要在 db/get-person! 函数之前调用它。否则,该值将过时。

所以我想知道:

  • 我该怎么做?
  • 无论如何,映射中值的顺序是否足以保证一个函数总是在另一个函数之前被调用?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    不,地图没有顺序。对于小的文字映射它可能会工作,但你不应该依赖它,对于较大的映射它确实会失败:

    user=> {0 (println 0) 1 (println 1) 2 (println 2) 3 (println 3) 4 (println 4) 5 (println 5) 6 (println 6) 7 (println 7) 8 (println 8) 9 (println 9)}
    0
    7
    1
    4
    6
    3
    2
    9
    5
    8
    {0 nil, 7 nil, 1 nil, 4 nil, 6 nil, 3 nil, 2 nil, 9 nil, 5 nil, 8 nil}
    

    但使用let 绑定总是很容易强制排序,这些绑定在let 正文之前按顺序进行评估。

    (let [person (db/get-person!)]
      {:person person :violations ...})
    

    【讨论】:

    • 除了使用let 按顺序评估参数的方法之外,调用hash-maparray-map 函数也可以工作:(hash-map 0 (println 0) 1 (println 1))。评估顺序是从左到右 (stackoverflow.com/a/4815462/1008794)。
    【解决方案2】:

    读者会将代码中的映射读入映射,对此您不应做任何排序假设,因此不要依赖这些值的评估顺序。 (实际上,它是一个数组映射,它的求值顺序可能与词法定义的顺序相同,但您不应该依赖它。)

    (defn process-request [request]
      (if (not (db/empty?))
        (let [violations (:violations (process-violations request))
              person (db/get-person!)]
          {:person person :violations violations})
        {:person {} :violations ["no-person"]}))
    

    会更安全。

    【讨论】:

      猜你喜欢
      • 2012-06-23
      • 2011-07-13
      • 1970-01-01
      • 2014-07-22
      • 2017-07-10
      • 2017-03-04
      • 2021-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多