2011-08-29 7 views
5

Expresiones como¿Cómo puedo escribir f (g (h (x))) en Scala con menos paréntesis?

ls map (_ + 1) sum 

son preciosas porque son de izquierda a derecha y no anidados. Pero si las funciones en cuestión se definen fuera de la clase, es menos bonita.

Siguiendo an example me trataron

final class DoublePlus(val self: Double) { 
    def hypot(x: Double) = sqrt(self*self + x*x) 
} 

implicit def doubleToDoublePlus(x: Double) = 
    new DoublePlus(x) 

que funciona muy bien en lo que puedo decir, aparte de

  1. escribir mucho para un método de

  2. lo que necesita saber de antemano que desea utilizarlo de esta manera

¿Hay algún truco que resuelva esos dos problemas?

+0

¿Qué hay de malo en definir hypot en un objeto de utilidad y luego usarlo como 'hypot (3,4)'? Parece la mejor opción aquí. – IttayD

Respuesta

12

Puede llamar andThen en un objeto función:

(h andThen g andThen f)(x) 

No se puede llamar a métodos directamente, así que quizás sus necesidades h para convertirse en (h _) para transformar el método en una función parcialmente aplicada. El compilador traducirá nombres de métodos subsecuentes a funciones automáticamente porque el método andThen acepta un parámetro Function.

También es posible usar el pipe operator|> a escribir algo como esto:

x |> h |> g |> f 
+0

¡Agradable! Mi favorito es el tubo. – Owen

2

Enriquecimiento de una clase/interfaz existente con una conversión implícita (que es lo que hizo con doubleToDoublePlus) tiene que ver con el diseño de la API cuando algunos las clases no están bajo tu control. No recomiendo hacerlo a la ligera solo para guardar unas pocas teclas o tener unos pocos paréntesis menos. Por lo tanto, si es importante poder escribir val h = d hypot x, las pulsaciones de teclas adicionales no deberían ser una preocupación. (Puede haber problemas con la asignación de objetos, pero eso es diferente).

El título y su ejemplo también no coinciden:

f(g(h(x))) se puede reescribir como f _ compose g _ compose h _ apply x si su preocupación es sobre paréntesis o si f, g, h son objetos función en lugar de def.

Pero ls map (_ + 1) sum no son llamadas anidadas como dices, así que no estoy seguro de cómo se relaciona eso con el título. Y aunque es precioso usar, los diseñadores de biblioteca/lenguaje hicieron muchos esfuerzos para que sea fácil de usar y debajo del capó no es simple (mucho más complejo que su hypot ejemplo).

+0

Bueno, * son * llamadas anidadas en cierto sentido: el resultado de cada paso se convierte en el argumento 'this' para la próxima llamada. En otros idiomas, esta anidación sería explícita. Mi problema es que si un argumento en particular es un argumento 'this' no es muy significativo desde el punto de vista funcional, es solo por este hecho que obtienes una buena sintaxis de llamadas. – Owen

2
def fgh (n: N) = f(g(h(n))) 
val m = fgh (n) 
0

Tal vez esto, observar cómo una se proporciona:

def componen [A, B, C] (f: B => C, g: A => B): A => C = (a: A) => f (g (a))

básicamente como la respuesta anterior combina las funciones deseadas con una intermedia que luego puede usar fácilmente con el mapa.

Cuestiones relacionadas