【问题标题】:Can a var be a key in a map?var 可以作为地图中的键吗?
【发布时间】:2014-03-09 20:13:44
【问题描述】:
(def nextStudentNumber 1000)

(defn s
  [lastName firstName]
  (let [student {:nextStudentNumber {:lastName lastName
                                     :firstName firstName
                                     :grades {}
                                     :id (inc nextStudentNumber)}}]

在这种情况下,我创建了 var nextStudentNumber,并且我想要映射在学生身上发生变化的键。

【问题讨论】:

  • 也许只有我一个人,但不清楚你在问什么。
  • nextStudentNumber 应该是一个原子,否则每个学生都会有相同的 id
  • 虽然不是对您问题的直接回答,但不久前我问了一个类似的“表弟”问题。 stackoverflow.com/questions/11937495/…可能对你有帮助。

标签: map clojure


【解决方案1】:

是的,就像任何对象一样,var 可以是映射中的键:

{#'foo 42}
=> {#'user/foo 42}

由于这对您没有帮助,这里是您问题的示例构造:

(->> [{:name "Mara"} {:name "Lara"} {:name "Clara"}]
     (map-indexed #(assoc %2 :id %1)) ;; assign an ID to each student
     (group-by :id)) ;; Create a hash-map where students can be looked up by ID
=> {0 [{:name "Mara, :id 0}], 1 [{:name "Lara", :id 1}]
    2 [{:name "Clara", :id 2}]}

请注意,此示例有点多余(因为可以通过使用索引调用向量直接在向量中执行索引查找)。

但是,它展示了使用不可变数据的基本思想:在独立的步骤中,您生成 ID 并进行分组。您可以通过多种方式组合这些步骤,例如为新学生生成 ID、将它们添加到现有学生的集合中以及按 ID 对它们进行分组。请注意,(group-by :id) 步骤的工作方式与 ID 的生成方式无关,并且可以容忍两个学生具有相同 ID 的情况,然后您可以检测和处理。

命令式方法在函数式 Clojure 世界中非常不典型。如果您有许多分配学生的函数(并且在您的想法中应该调用s),不如让它们成为纯函数,让它们返回学生集合并给它们命名,如load-students-from-filegenerate-ids,并使用concat之类的结构, into 组合它们返回的集合,而不需要弄乱状态,直到您对学生数据进行 I/O。

如果出于好奇,您仍然想弄乱状态,这里是另一个(相当单一的)代码示例:

(def student-count (atom 0))
(def students-by-id (atom {}))

(defn add-student! [first-name last-name]
   (let [next-id (swap! student-count inc)]
     (swap! students-by-id
            assoc next-id {:first-name first-name, :last-name last-name
                           :id next-id})))

E. g.:

(add-student! "Mara" "Mad")
(add-student! "Lara" "Light")
(@students-by-id 1)
=> {:first-name "Lara", :last-name "Light", :id 1}

如您所见,这里一步完成。

【讨论】:

    【解决方案2】:
    {:nextStudentNumber {:lastName lastName
                         :firstName firstName
                         :grades {}
                         :id (inc nextStudentNumber)}
    

    我假设您希望将其转换为:

    {:1000 {:lastName lastName
            :firstName firstName
            :grades {}
            :id (inc nextStudentNumber)}
    

    在这种情况下你会想要:

    {(keyword (str nextStudentNumber)) {:lastName lastName
                                        :firstName firstName
                                        :grades {}
                                        :id (inc nextStudentNumber)}
    

    还有一些其他的臭东西,比如骆驼案和inc。我们在 clojure 中使用悬浮蛇,所以 lastName 将是 last-name。我不知道你在用 inc 做什么,但它会散发出强烈的命令式氛围。

    【讨论】:

    • inc 不会改变 var,所以每个学生都会有相同的 :id
    猜你喜欢
    • 1970-01-01
    • 2014-11-05
    • 2015-04-02
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    相关资源
    最近更新 更多