在Clojure中访问列表内的地图

3
这里是代码:
(def entry {:name tempName :num tempNum})

(def tempList '(entry))

(println (get (nth tempList 0) (:name)))

Exception in thread "main" java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :name

在这段代码中,我定义了一个名为entry的map,其中包含一个:name和一个:num,然后将其放入列表中,然后尝试打印列表中第一个(也是唯一的)元素的:name字段。(至少我认为我的代码是这样做的:o)
在将其放入列表之前,我可以从entry map中访问name,但是一旦它被放入列表中,我就会得到这个错误。我应该给什么参数?
4个回答

3

有两个问题。

首先,对于包含需要解析符号的列表(例如您的情况中的符号条目),您必须使用语法引用(反引号)而不是常规引用(单引号);所以这行代码:

(def tempList '(entry))

should be:

(def tempList `(entry))

或者只是使用向量(在Clojure中更加惯用且易于使用):

(def tempList [entry]) ; no quoting needed for vectors

然后,更改这一行。
(println (get (nth tempList 0) (:name)))

转换为以下内容之一:

(println (get (nth tempList 0) :name))

或者这样:
(println (:name (nth tempList 0)))

2

在列表中使用nth是不明智的,因为每次都需要进行线性搜索来检索元素。在这里使用向量是正确的集合类型。

向量是索引到值的“映射”。如果您使用向量而不是列表,则可以执行以下操作:

(:name (tempList 0))

或者:

(get (get tempList 0) :name)

或者:

(get-in tempList [0 :name]))

1
我会这样编写你的代码:

(def entry {:name tempName :num tempNum})

(def tempList (list entry))

(println (:name (first tempList)))

请注意,使用first比使用nth更加简洁,关键字可以作为函数在映射中查找自己。另一种等效的方法是组合函数并将其应用于列表:
((comp println :name first) tempList)

1

在第三行中去掉(:name)的括号。 :keywords是以map为参数的函数,它们可以“自我查找”,这非常方便,但在这种情况下会使错误略微更加混乱。

(get (nth '({:name "asdf"}) 0) :name))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接