Доступ к карте внутри списка в Clojure - PullRequest
3 голосов
/ 14 июля 2009

Вот код:

(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, содержащую a: name и a: num, затем помещаю ее в список, затем пытаюсь напечатать поле: name первого (и единственного) элемента список. (или, по крайней мере, это то, что я думаю, что мой код делает: o)

Я могу получить доступ к имени с карты входа, прежде чем поместить его в список, но как только оно появится в списке, я получаю эту ошибку. Какие аргументы я должен дать?

Ответы [ 4 ]

3 голосов
/ 14 июля 2009

Есть две проблемы.

Во-первых, для списков, которые содержат символы, которые необходимо разрешить (например, ввод символов в вашем случае), вы должны использовать синтаксическая кавычка (обратная черта) вместо обычной кавычки (апостроф); так вот эта строка:

(def tempList '(entry))

должно быть:

(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 голосов
/ 14 июля 2009

Использование nth в списке - плохая идея, потому что он должен выполнять линейный поиск для извлечения вашего элемента каждый раз. Векторы - правильный тип коллекции для использования здесь.

Векторы - это «карты» индексов для значений. Если вы используете вектор вместо списка, вы можете сделать это:

(:name (tempList 0))

Или:

(get (get tempList 0) :name)

Или:

(get-in tempList [0 :name]))
1 голос
/ 21 июля 2009

Я бы написал ваш код так:

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

(def tempList (list entry))

(println (:name (first tempList)))

Обратите внимание, что first гораздо точнее, чем использование nth, и ключевые слова могут выступать в качестве функций для поиска себя на карте. Другой эквивалентный подход состоит в том, чтобы составить функции и применить их к списку:

((comp println :name first) tempList)
1 голос
/ 14 июля 2009

снять () с (: name) в 3-й строке. : ключевые слова - это функции, которые принимают карту в качестве аргумента и «ищут себя», что очень удобно, хотя в этом случае ошибка несколько запутывает

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