Ich baue einen Simulator, der einige Ereignisse analysiert STDIN
und "ausführt". Mein Hintergrund ist heutzutage hauptsächlich funktionale Programmierung, daher schien es naheliegend, so etwas zu tun:
data Event = Thing1 String Int | Thing2 Int | Thing3 String String Int
Parse :: String -> [Event]
Simulate :: [Event] -> [Result]
wo simulieren wäre
case event
of Thing1 a b => compute for thing one
| Thing2 a => compute for thing two
usw. Was ist die idiomatische Art, solche Dinge in Java zu tun? Googeln hat mich in Richtung verschachtelter Klassen und des Besuchermusters gelenkt, aber das scheint bei meinem Versuch ziemlich schwer zu sein. Typ Löschung scheint mich hart zu bekämpfen. Können Sie mir einen Überblick darüber geben, wie das richtig gemacht aussehen würde?
java
design
visitor-pattern
pattern-matching
Closeparen
quelle
quelle
Event
Typ beispielsweise konzeptionell gleichbedeutend mit einsInt
und zweiMaybe Strings
?Antworten:
Der Autor von 'Functional Programming in Scala' gibt eine schöne Illustration des Besten, was in Java auf typsichere Weise erreicht werden kann:
http://blog.higher-order.com/blog/2009/08/21/structural-pattern-matching-in-java/
Im Wesentlichen wird eine Church-Codierung der Fälle verwendet, um sicherzustellen, dass sich der Compiler beschwert, wenn welche fehlen.
Die Einzelheiten sind nicht ohne weiteres zusammengefasst und sind in der Tat so gut in dem Artikel behandelt , dass es keinen Sinn , sie hier bei der Wiedergabe (das ist , was Hyperlinks sind für richtig?).
quelle
t.match
mit den drei Methoden übergeben, anstatt drei Funktionen zu übergeben. (Der verlinkte Artikel verwechselt Besuchermuster mit doppeltem Versand - Besucher ist ein Muster zum Abstrahieren der Iteration über ein Netzwerk, nicht zum Auswählen von Mustern)public static int depth(Tree t)
wo er verkettet verwendet, wenn eine Instanz davon, wenn der "richtige" Weg, dies in Java zu tun, darin besteht, eine Schnittstelle mit der Methode zu definieren:public int depth()
und Verwenden Sie Polymorphismus. Es scheint wie ein Strohmann.Es gibt so etwas nicht wirklich, da Java (die Sprache) grundsätzlich unerlässlich ist.
Wenn Sie auf der JVM ausgeführt werden können, aber nicht auf die Java- Sprache beschränkt sind , können Sie Scala untersuchen, mit dem mithilfe des Mustervergleichs etwas wie oben erreicht werden kann .
Ansonsten sind Sie meiner Meinung nach darauf beschränkt, Ihre verschiedenen Fälle manuell anzupassen und Methoden entsprechend aufzurufen oder Subtypen von 'Event' zu definieren und mithilfe von Polymorphismus bestimmte Methoden für jeden Subtyp aufzurufen.
quelle
Schauen Sie sich https://github.com/johnlcox/motif an , eine Scala-ähnliche "Pattern Matching" -Bibliothek für Java 8.
Nicht annähernd so schön wie ML / Erlang / Haskell, sieht aber dennoch viel aussagekräftiger aus als die meisten anderen.
quelle
Sie können eine Aufzählung und eine Schnittstelle verwenden, um die Simulationsmethode wie folgt zu überschreiben:
Nehmen wir an, Sie haben
Event event
. Dann können Sie es auf zwei Arten verwenden:oder
Der Konstruktor wird jedoch automatisch von der JVM aufgerufen. Um also auch die Parameter dort zu speichern, müssen Sie Eigenschaften mit Accessoren usw. hinzufügen.
Alternativ können Sie Ihre Ereignisse als konstante Zeichenfolgen codieren und das
switch
Konstrukt verwenden. In diesem Fall würden Sie dies tunusw. Aber ja, es gibt nichts Natives, das den Mustervergleich direkt nachahmt :(
quelle
Das Besuchermuster oder sein kirchliches Kodierungsäquivalent ist der richtige Weg. In Java ist es ziemlich ausführlich, aber hoffentlich können Tools wie Derive4J (ein von mir gepflegter Anmerkungsprozessor) oder Adt4J das Boilerplate generieren. Mit einem solchen Tool wird Ihr Beispiel:
Derive4J generiert die Events-Klasse, die eine fließende Mustervergleichssyntax bietet (mit umfassender Überprüfung, ob alle Fälle behandelt werden).
quelle