2011-02-03 14 views
8

poco me escribió lo siguiente pedazo de Scala:¿La opción de ajustar un valor es un buen patrón?

val f: File = ... // pretend this file came from somewhere 
val foo = toFoo(io.Source.fromFile(f).mkString) 

Realmente no me gusta la forma en que esto fluyó. Para entender lo que está pasando, usted tiene que comenzar con f en el medio, lee de izquierda a fromFile, lea derecho a mkString, lea la izquierda de nuevo a toFoo. Ugh.

Especialmente después de acostumbrarse a las transformaciones funcionales de secuencias, esto es difícil de leer. Mi próximo intento se ve así:

val foo = Some(f) 
    .map(io.Source.fromFile) 
    .map(_.mkString) 
    .map(toFoo) 
    .get 

Me gusta el flujo de esta mucho mejor. Puedes ver lo que sucede. ¿Es esto un buen uso de la clase Option? ¿O lo estoy abusando? ¿Hay un mejor patrón que pueda usar para lograr el mismo flujo?

Respuesta

25

Esto está perfectamente bien. Sin embargo, hay un método |> en Scalaz que hace algo mejor, y se pueden crear por sí mismo si no se desea que todos los Scalaz:

class Piper[A](a: A) { def |>[B](f: A => B) = f(a) } 
implicit def pipe_everything[A](a: A) = new Piper(a) 

f |> io.Source.fromFile |> {_.mkString} |> toFoo 

Personalmente, tiendo a escribir un montón de código que requiere paréntesis y me gustan los métodos mejores que los operadores en la mayoría de los casos, por lo que en mi código que normalmente llamo |> "uso", pero es el mismo trato:

f.use(io.Source.fromFile).use(_.mkString).use(toFoo) 

en Scala 2.11 o posterior, puede obtener el mismo comportamiento y rendimiento mejorado Ce con (un poco) menos sintaxis:

implicit class Piper[A](private val a: A) extends AnyVal { 
    def |>[B](f: A => B) = f(a) 
} 
+0

¡es un fragmento que incluyo en cada proyecto que escribo! Debería estar realmente en la biblioteca estándar ... –

+0

@Kevin - De acuerdo, debería estar en la biblioteca estándar. También lo tengo en todos mis proyectos, ya que tengo una biblioteca estándar que incluyo en todos los proyectos que escribo, y esta es una de las cosas que hay en ella. –

+0

Una versión actualizada de la actual generación: 'clase implícita Piper [A] (a: A) {def |> [B] (f: A => B) = f (a)} se extiende AnyVal' –

4

Se agrega a toFooString a través del proxeneta mi patrón biblioteca. Entonces se convierte en:

val foo = Source fromFile f mkString() toFoo 
+0

o '(Fuente de File f mkString) toFoo', solo una preferencia personal. –

+4

@Kevin Desearía que hubiera un símbolo que podría significar "sin lista de parámetros". Si fuera obligatorio, resolvería todos los problemas de notación de Postfix. –

5

no tengo problemas con las otras respuestas que se dan aquí, pero lo que pensar en cambiar el nombre de Tofoo en algo que 'fluye' mejor? Es decir, Tofoo realmente huele a algo que debería estar en la derecha de una expresión, pero si cambia el nombre en otra cosa, podría encajar en el izquierda también.

// toFoo, as defined by you 
val foo = toFoo(io.Source.fromFile(f).mkString) 
// Same function, different name 
val foo = createFooFrom(io.Source.fromFile(f).mkString) 
+0

De acuerdo, pero fue solo un ejemplo :-) – leedm777

Cuestiones relacionadas