2009-07-13 5 views
3

Hier ist der Code Zugriff:eine Karte in einer Liste in Clojure

(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 diesem Stück Code, definiere ich eine Karte genannt Eintrag enthält einen: Namen und a: num, dann habe ich sie in einer Liste , dann versuche ich das Name-Feld des ersten (und einzigen) Elements der Liste zu drucken. (oder zumindest das ist, was ich denke, mein Code tut: o)

Ich kann Name aus der Eintragsliste zugreifen, bevor ich es in die Liste, aber sobald es in der Liste ist, bekomme ich diesen Fehler. Was soll ich geben?

Antwort

3

Es gibt zwei Probleme.

Zuerst müssen Sie für Listen, die zu lösende Symbole enthalten (wie der Symboleintrag in Ihrem Fall), syntax-quote (Backtick) anstelle von regulären Anführungszeichen (Apostroph); so dass diese Zeile:

(def tempList '(entry)) 

sollte sein:

(def tempList `(entry)) 

oder einfach (mit einem Vektor, der mehr idiomatischen und einfacher in Clojure verwenden):

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

Dann ändern diese Linie

zu e ither dies:

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

oder dies:

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

nehmen Sie die() aus von (: Name) auf der 3. Zeile. : Schlüsselwörter sind Funktionen, die eine Karte als Argument nehmen und „schauen sich nach oben“, was ganz praktisch ist, wenn es der Fehler in diesem Fall etwas verwirrend macht

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

Mit nth auf einer Liste ist eine schlechte Idee, weil es muss eine lineare Suche durchführen, um jedes Mal dein Element zu erhalten. Vektoren sind der richtige Sammlungstyp, den Sie hier verwenden können.

Vektoren sind "Karten" von Indizes zu Werten. Wenn Sie einen Vektor anstelle einer Liste verwenden, können Sie dies tun:

(:name (tempList 0)) 

Oder:

(get (get tempList 0) :name) 

Oder:

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

würde ich Code wie folgt schreiben:

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

(def tempList (list entry)) 

(println (:name (first tempList))) 

Beachten Sie, dass first ist viel besser als die Verwendung nth, und Schlüsselwörter können als Funktionen fungieren, um sich in der Karte zu suchen. Ein anderer äquivalenter Ansatz besteht darin, die Funktionen zu erstellen und sie auf die Liste anzuwenden: