Angesichts einer verbindlichen Form wie [{a :a} {b :b}]
Wie finde ich alle Symbole? (a b)
Wie kann man alle Symbole in einer verbindlichen Form finden?
Antwort
Der naive Ansatz wäre, nur die Bindungsform als eine verschachtelte Sammlung zu behandeln, alle Symbole in dieser Sammlung zu finden, und gibt die Reihenfolge dieser Symbole:
(defn symbols [x]
(filter symbol? (tree-seq coll? seq x)))
(symbols '[{a :a} {b :b}])
;;=> (a b)
jedoch als @amalloy noted, diese funktioniert nicht in allen Fällen. Hier sind einige Beispiele, bei denen die obige Implementierung von symbols
ein unerwünschtes Ergebnis gibt:
;; & isn't actually bound to anything
(symbols '[foo & bar])
;;=> (foo & bar)
;; duplicates
(symbols '{x :foo :or {x :bar}})
;;=> (x x)
;; keys and default values are evaluated, not bound
(symbols '{x (keyword "foo") :or {x (keyword 'bar)}})
;;=> (x keyword x keyword quote bar)
;; namespaced keywords and symbols don't work
(symbols '{:keys [::foo :bar/baz qux/quux]})
;;=> (qux/quux)
Er schlägt vor, mit dem eingebauten in destructure
Funktion statt, sondern wie er in seiner Antwort zeigte, dies einigen Müll verursacht in der zeigen, Ergebnis:
(take-nth 2 (destructure '[{:keys [x]} (last y)]))
;;=> (map__10938 map__10938 x)
Während dieser technisch der Liste der Symbole gibt, die Clojure binden werden, dass map__10938
nur eine Implementierung Artefakt ist, und hat nichts mit der Destrukturierung Sprache selbst zu tun.
Zum Glück ist es nicht zu schwierig, die Bindungsform manuell und montiert eine Reihe von Symbolen zu analysieren, von der ursprünglichen Bindungsform genommen, das gebunden werden würde:
(require '[clojure.set :as set])
(defn symbols [binding]
(cond
(symbol? binding)
#{binding}
(vector? binding)
(apply set/union (map symbols (remove #{'& :as} binding)))
(map? binding)
(apply set/union
(for [[k v] binding]
(case k
:or #{}
:as #{v}
(:keys :strs :syms) (set (map (comp symbol name) v))
(symbols k))))))
genial, danke! –
Das sieht mir ziemlich gut. Sie können Ihren 'cond' ziemlich viel vereinfachen, um' (case k: oder # {},: as # {v}, (: keys: strs: syms) (setzen ...), (symbols k)) ' – amalloy
@amalloy Cool, danke! :) Ich wusste nicht, dass du das mit 'case' machen kannst. –
Viel besser clojure.core/destructure
zu bedienen ist, welches versteht, welche Symbole Namen sind, die gebunden werden, anstatt Werte, die auseinander genommen werden. Betrachten wir zum Beispiel:
(let [{:keys [x]} (last y)]
x)
In diesem Zusammenhang Sie mit ziemlicher Sicherheit nicht wollen last
in der Liste der Symbole enthalten, vorausgesetzt, dass Sie diese verwenden, um besser eine Destrukturierung spec zu verstehen. Und wenn Sie destructure
nennen, es sagt Ihnen genau, welche Namen zu gebunden werden, welche Werte:
user> (destructure '[{:keys [x]} (last y)])
[map__10938 (last y)
map__10938 (if (clojure.core/seq? map__10938)
(clojure.lang.PersistentHashMap/create (clojure.core/seq map__10938))
map__10938)
x (clojure.core/get map__10938 :x)]
Jetzt auf der einen Seite, Sie werden immer ein Symbol, das nicht tatsächlich wurde durch den Anrufer eingegeben, aber das ist wahrscheinlich immer noch nützlich, weil es Ihnen sagt, was Clojure tatsächlich tun wird, um diesen Ausdruck zu handhaben. Um nur die linke Seite zu erhalten, dh die Namen, die gebunden werden, können Sie
(take-nth 2 (destructure '[{:keys [x]} (last y)]))
Er fragt nicht nach beiden Hälften einer Bindung (z. B. '{{: keys [x]} (last y)]'); er möchte nur die Symbole auf der * linken * Seite der Bindung finden. Zum Beispiel könnte ein Ausdruck wie '([[{a: a} {b: b}] [{: a: foo} {: b: bar}]] [ab])' aussehen, aber wie er in seine Frage, er will nur nach Symbolen im '[{a: a} {b: b}]' Teil suchen. –
Auch wenn du nur die linke Hälfte hast, können sich einige Symbole hineinschleichen, die keine Namen sind, die gebunden werden. Zum Beispiel '{: keys [x]: oder {x (range 10)}}' - wollen Sie wirklich 'range' von dieser Funktion zurückgeben? – amalloy
Ah, cool! Ich ging zurück über den [Clojure Destrukturierungsleitfaden] (http://clojure.org/guides/destructuring), und es sieht so aus, als ob es eine Menge Dinge gibt, die man mit der Destrukturierung machen kann, von denen ich nichts wusste.Ich habe meine Antwort bearbeitet, um diese Komplexitäten wiederzugeben. –
- 1. Wie kann ich alle Symbole in einer SVG-Datei anzeigen?
- 2. Selen erhalten alle Elemente in einer Form
- 3. alle Bedienelemente in Form
- 4. Wie listet man alle Symbole auf, die em ++ gefunden hat?
- 5. Wie alle Teil einer Zeichenfolge in PHP finden
- 6. Wie kann ich Symbole in einer Zeile von VB
- 7. wie man Symbole in einer reaktiven nativen Symbolleiste anzeigt/versteckt
- 8. Wie man mathematische Symbole wie Theta zeigt
- 9. Wie man Symbole in Ruby versteht
- 10. Wie kann man die Symbole <und ≤ in xml ausschließen?
- 11. wie alle Panels in Windows-Form ausblenden?
- 12. Symbole im Textfeld gegangen, als Form Auto
- 13. Xcode kann keine Symbole für die x86_64-Architektur finden
- 14. jQuery finden Eltern Form
- 15. Wie löst man alle in einer Abfrage?
- 16. shared object kann keine Symbole im Hauptbinär finden, C++
- 17. Wie kann ich alle Guids in einem Text finden?
- 18. Verbunden kann Symbole nicht finden, aber Bibliotheken werden gelesen und Symbole existieren
- 19. Mac: Wie man Symbole aus einer ausführbaren Datei exportiert?
- 20. Wie alle Spiele eines Musters in einer Zeichenfolge finden regex
- 21. Wie alle direkten Subklassen einer Klasse mit .NET Reflexion finden
- 22. Wie man Symbole aus einer Zeichenfolge mit Python entfernt?
- 23. PHP Finden Sie alle Vorkommen einer Teilzeichenfolge in einer Zeichenfolge
- 24. Finden Sie alle Instanzen einer Klasse beim Debuggen in Eclipse
- 25. Wo kann ich JQuery UI CSS-Symbole finden?
- 26. wie in einer Form odoo
- 27. WinDbg kann nicht mfc90 Version 9.0.30729.4148 Symbole auf msdl.microsoft.com finden
- 28. Wie kann ich alle Initialisierungen in einem Text finden?
- 29. Sellerie in Django, Wie kann ich alle Aufgaben finden?
- 30. Actionscript3: Wie listet man die Pixel einer Form auf?
verwenden Do '&' und '_' zählen? –
ah, ich hatte sie nicht berücksichtigt, aber ja, es scheint, ich kann sie einfach aus der Ausgabe entfernen. –