Clojure case-Anweisung mit Klassen

8

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

zurückgegeben

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?

    
Chris 19.08.2012, 18:34
quelle

3 Antworten

14

Ich glaube, case behandelt die Klassennamen als Literalsymbole - sie werden nicht in tatsächliche Klassen aufgelöst:

%Vor%

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 :

zu aktivieren %Vor%

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.

    
Rafał Dowgird 19.08.2012, 19:19
quelle
8

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.

    
ponzao 19.08.2012 19:43
quelle
2

Wenn Sie nach einem alternativen Weg suchen, um dies zu erreichen, werfen Sie einen Blick auf condp :

%Vor%     
Nico Schneider 03.10.2017 00:53
quelle

Tags und Links