[英]Accessing a map inside a list in Clojure
Here's the code : 这是代码:
(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
In this bit of code, I define a map called entry containing a :name and a :num, then I put it in a list, then I try to print the :name field of the first (and only) element of the list. 在这段代码中,我定义了一个名为entry的映射,其中包含:name和:num,然后将其放入列表中,然后尝试打印列表中第一个(也是唯一一个)元素的:name字段。 (or at least this is what I think my code does :o)
(或者至少这是我认为我的代码可以做到的:o)
I can access name from the entry map before I put it in the list, but once it's in the list I get this error. 在将名称放入列表之前,我可以从条目映射访问名称,但是一旦将其放入列表中,就会出现此错误。 What args am I supposed to give ?
我应该给什么参数?
There are two problems. 有两个问题。
First, for lists that contain symbols to be resolved (like the symbol entry in your case), you have to use syntax-quote (backtick) instead of regular quote (apostrophe); 首先,对于包含要解析符号的列表(例如您的案例中的符号条目),您必须使用语法引号 (反引号)而不是常规引号(撇号); so this line:
所以这行:
(def tempList '(entry))
should be: 应该:
(def tempList `(entry))
or just (using a vector, which is more idiomatic and easier to use in Clojure): 或只是(使用向量,它在Clojure中更惯用且更易于使用):
(def tempList [entry]) ; no quoting needed for vectors
Then, change this line 然后,更改此行
(println (get (nth tempList 0) (:name)))
to either this: 为此:
(println (get (nth tempList 0) :name))
or this: 或这个:
(println (:name (nth tempList 0)))
Using nth
on a list is a bad idea because it has to do a linear search to retrieve your element, every time. 在列表上使用
nth
是个坏主意,因为它每次都必须进行线性搜索来检索元素。 Vectors are the right collection type to use here. 向量是在此处使用的正确集合类型。
Vectors are "maps" of indices to values. 向量是索引到值的“映射”。 If you use a vector instead of a list you can do this:
如果使用向量而不是列表,则可以执行以下操作:
(:name (tempList 0))
Or: 要么:
(get (get tempList 0) :name)
Or: 要么:
(get-in tempList [0 :name]))
take the ( ) off from (:name) on the 3rd line. 从第三行的(:name)取下()。 :keywords are functions that take a map as an argument and "look themselves up" which is quite handy though it makes the error slightly more confusing in this case
:keywords是将地图作为参数并“查找自己”的函数,虽然在这种情况下会使错误稍微混乱,但它非常方便
(get (nth '({:name "asdf"}) 0) :name))
I would write your code like this: 我会这样写你的代码:
(def entry {:name tempName :num tempNum})
(def tempList (list entry))
(println (:name (first tempList)))
Note that first
is much neater than using nth
, and keywords can act as functions to look themselves up in the map. 请注意,
first
比使用nth
更整洁,关键字可以充当在地图中查找自己的函数。 Another equivalent approach is to compose the functions and apply them to the list: 另一种等效的方法是组合功能并将其应用于列表:
((comp println :name first) tempList)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.