Tengo un entrante de líneas de flujo perezosas de un archivo que estoy leyendo con tail-seq (contrib - ahora!) Y quiero procesar esas líneas una tras otra con varias "funciones de escucha" que toma acción que depende de hits de re-seq (u otras cosas) en las líneas.Un argumento, muchas funciones
He intentado lo siguiente:
(defn info-listener [logstr]
(if (re-seq #"INFO" logstr) (println "Got an INFO-statement")))
(defn debug-listener [logstr]
(if (re-seq #"DEBUG" logstr) (println "Got a DEBUG-statement")))
(doseq [line (tail-seq "/var/log/any/java.log")]
(do (info-listener logstr)
(debug-listener logstr)))
y funciona como se esperaba. Sin embargo, hay un montón de duplicación de código y otros pecados en el código, y es aburrido actualizar el código.
Un paso importante parece ser la aplicación de muchas de las funciones de un argumento, es decir
(listen-line line '(info-listener debug-listener))
y el uso que en lugar de la declaración propensos do-aburrido y error.
He intentado el siguiente método aparentemente inteligente:
(defn listen-line [logstr listener-collection]
(map #(% logstr) listener-collection))
pero esto sólo sirve para hacer
(nil) (nil)
hay funciones de clase lazyiness o primero me pican a ciencia cierta, pero ¿dónde pongo el ¿aplicar?
También estoy abierto a un enfoque radicalmente diferente al problema, pero esta parece ser una manera bastante sensata para empezar. Las macros/métodos múltiples parecen ser excesivos/incorrectos por ahora.
Esto es muy elegante y también me dio una idea más profunda de Clojure (al igual que la respuesta anterior). Gracias, Alex! – claj
@claj eres muy amable. Si desea llevar más allá el nivel de abstracción, realice un pequeño cambio y tenga el segundo argumento para que el oyente sea una función para llamar con logstr. Eso permite diferentes acciones basadas en la coincidencia de entrada. En ese momento, básicamente hemos reinventado un multimétodo. ¡Las funciones como entidades de primera clase permiten abstracciones muy potentes! –