Estoy construyendo un simulador que analiza algunos eventos STDIN
y los "ejecuta". Mi experiencia es principalmente programación funcional en estos días, por lo que parecía natural hacer algo como esto:
data Event = Thing1 String Int | Thing2 Int | Thing3 String String Int
Parse :: String -> [Event]
Simulate :: [Event] -> [Result]
donde simular sería
case event
of Thing1 a b => compute for thing one
| Thing2 a => compute for thing two
¿Cuál es la forma idiomática de hacer este tipo de cosas en Java? Buscar en Google me ha señalado en la dirección de las clases anidadas y el patrón de visitante, pero eso parece bastante pesado en mi intento. El borrado de tipo parece estar luchando contra mí, duro. ¿Podrías mostrarme un resumen de cómo se vería correctamente?
java
design
visitor-pattern
pattern-matching
closeparen
fuente
fuente
Event
tipo conceptualmente equivalente a tener unoInt
y dosMaybe Strings
?Respuestas:
El autor de 'Programación funcional en Scala' ofrece una buena ilustración de lo mejor que se puede lograr en Java de una manera segura:
http://blog.higher-order.com/blog/2009/08/21/structural-pattern-matching-in-java/
Esencialmente, utiliza una codificación de la Iglesia de los casos para garantizar que el compilador se quejará si falta alguno.
Los detalles no se resumen fácilmente y de hecho están tan bien cubiertos en el artículo que no tiene sentido en la reproducción de ellos aquí (eso es lo que son los hipervínculos de verdad?).
fuente
t.match
con los tres métodos en lugar de pasar tres funciones. (el artículo vinculado confunde el patrón de Visitante con el envío doble: el visitante es un patrón para abstraer la iteración a través de una red, no para seleccionar patrones)public static int depth(Tree t)
donde usa encadenado si una instancia de cuando la forma "correcta" de hacer esto en Java es definir una interfaz con el método:public int depth()
y usar polimorfismo Parece un hombre de paja.Realmente no existe tal cosa, dado que Java (el lenguaje) es fundamentalmente imprescindible.
Si puede ejecutar en la JVM, pero no está restringido al lenguaje Java , podría investigar Scala, que lograría algo como lo anterior utilizando la coincidencia de patrones .
De lo contrario, creo que se verá reducido a hacer coincidir manualmente sus diversos casos y métodos de llamada según corresponda, o tal vez definir subtipos de 'Evento' y usar polimorfismo para invocar métodos particulares para cada subtipo.
fuente
Eche un vistazo a https://github.com/johnlcox/motif, que es una biblioteca de "coincidencia de patrones" similar a Scala para Java 8.
No es tan bueno como ML / Erlang / Haskell, pero aún se ve mucho más declarativo que la mayoría.
fuente
Puede usar una enumeración e interfaz, anulando el método de simulación, como este:
Digamos que tienes
Event event
. Luego puede usarlo de dos maneras:o
Pero la JVM llama automáticamente al constructor, por lo que para almacenar los parámetros allí, tendrá que agregar propiedades con accesores, etc.
Alternativamente, puede codificar sus eventos como cadenas constantes y usar la
switch
construcción, en cuyo caso lo haríaetc. Pero sí, no hay nada nativo que imite directamente la coincidencia de patrones :(
fuente
El patrón de visitante o su equivalente de codificación de la iglesia es el camino a seguir. Es bastante detallado en Java, pero es de esperar que herramientas como Derive4J (un procesador de anotaciones que mantengo) o Adt4J puedan generar el repetitivo. Usando tal herramienta, su ejemplo se convierte en:
Derive4J genera la clase Eventos que proporciona una sintaxis de coincidencia de patrones fluida (con una verificación exhaustiva de que se manejan todos los casos).
fuente