(def nextStudentNumber 1000)
(defn s
[lastName firstName]
(let [student {:nextStudentNumber {:lastName lastName
:firstName firstName
:grades {}
:id (inc nextStudentNumber)}}]
在这个例子中,我创建了var nextStudentNumber
,我想要映射那些在学生身上发生变化的键。
答案 0 :(得分:3)
是的,就像任何对象一样,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的情况,然后您可以检测并处理这些ID。
在功能性Clojure世界中,命令式方法非常不典型。如果您有许多分配学生的功能(并且在您的思考中应该调用s
),而是让它们变得纯粹,让他们返回学生的集合,并为他们命名,如load-students-from-file
,generate-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})))
电子。 G:
(add-student! "Mara" "Mad")
(add-student! "Lara" "Light")
(@students-by-id 1)
=> {:first-name "Lara", :last-name "Light", :id 1}
正如你所看到的,一切都在这里一步完成。
答案 1 :(得分:0)
{: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
做了什么,但却发出了强烈的祈祷声。