Ich möchte die Klasse eines bestimmten Objekts einschalten, um es zu codieren.
%Vor% Wenn ich (encoded-msg-for {})
aufruft, wird No matching clause: class clojure.lang.PersistentArrayMap
Was merkwürdig ist, ist, dass die Fälle in eine Hash-Map (mit den Klassen als Schlüssel und Strings als Werte) perfekt funktionieren.
Auch (= (class {}) clojure.lang.PersistentArrayMap)
ist wahr. Welcher Vergleich findet hier statt und wie kann ich entweder die Klasse des Objekts selbst oder (besser) etwas in seiner Hierarchie wechseln?
Ich glaube, case
behandelt die Klassennamen als Literalsymbole - sie werden nicht in tatsächliche Klassen aufgelöst:
Das ist ziemlich unintuitiv, aber so funktioniert es in Clojures case
. Wie auch immer, der idiomatische Weg besteht darin, defmulti
und defmethod
zu verwenden, anstatt type
:
Der Dispatcher verwendet das Prädikat isa?
, das sich gut mit den Vergleichen von Typen verhält, insbesondere funktioniert es gut mit Java-Vererbung.
Wenn Sie defmulti
nicht verwenden möchten, kann condp
in Ihrem Anwendungsfall case
ersetzen, da es die Testausdrücke richtig auswertet. Auf der anderen Seite bietet es keine konstante Zeitverteilung.
Wenn Sie nur auf die Klasse zugreifen, können Protokolle eine gute Lösung sein, da sie Sie (oder den Client Ihrer API) aktivieren. Um Implementierungen für andere Typen zu einem späteren Zeitpunkt bereitzustellen, hier ein Beispiel:
%Vor%Wenn Sie einen feinkörnigeren Versand benötigen, oder Sie wissen, dass die Erweiterung auf andere Typen nicht notwendig ist, dann könnte es in dieser Lösung zu viele Voreinstellungen geben.
Wenn Sie nach einem alternativen Weg suchen, um dies zu erreichen, werfen Sie einen Blick auf condp
:
Tags und Links class clojure switch-statement