software renault examples scala

renault - scala vs java



Componer y luego métodos (4)

Bien, esto:

addUhum _

es una expansión eta Convierte métodos en funciones. Por otro lado, esto:

addUhum(_)

es una función anónima De hecho, es una aplicación de función parcial, ya que este parámetro no se aplica y todo se convierte en una función. Se expande a:

x => addUhum(x)

Las reglas exactas para la expansión son un poco difíciles de explicar, pero, básicamente, la función "comenzará" en el delimitador de expresión más interno. La excepción son las aplicaciones de función parcial, donde la "x" se mueve fuera de la función, si se usa _ en lugar de un parámetro.

De todos modos, así es como se expande:

val ummThenAhem = x => addAhem(x).compose(y => addUmm(y))

Por desgracia, el tipo inferencer no sabe el tipo de x o y. Si lo desea, puede ver exactamente lo que intentó con el parámetro -Ytyper-debug .

Estoy siguiendo el tutorial Patrón de coincidencia y composición funcional en los métodos Scala compose y andThen . Hay un ejemplo:

scala> def addUmm(x: String) = x + " umm" scala> def addAhem(x: String) = x + " ahem" val ummThenAhem = addAhem(_).compose(addUmm(_))

Cuando intento usarlo obtengo un error:

<console>:7: error: missing parameter type for expanded function ((x$1) => addAhem(x$1).compose(((x$2) => addUmm(x$2)))) val ummThenAhem = addAhem(_).compose(addUmm(_)) ^ <console>:7: error: missing parameter type for expanded function ((x$2) => addUmm(x$2)) val ummThenAhem = addAhem(_).compose(addUmm(_)) ^ <console>:7: error: type mismatch; found : java.lang.String required: Int val ummThenAhem = addAhem(_).compose(addUmm(_))

Sin embargo, esto funciona:

val ummThenAhem = addAhem _ compose addUmm _

o incluso

val ummThenAhem = addAhem _ compose addUmm

¿Qué pasa con el código en el tutorial? ¿No es la última expresión la misma que la primera sin paréntesis?


Creo que el tutorial fue escrito para una versión anterior de Scala (probablemente 2.7.7 o anterior). Desde entonces, se han producido algunos cambios en el compilador, a saber, las extensiones del sistema de tipos, que ahora provocan que el tipo de inferencia falle en:

addUhum(_).compose(addAhem(_))

El levantamiento de una función aún funciona con esa sintaxis si solo escribe:

addUhum(_)


De la documentación compose :

Compone dos instancias de Función1 en una nueva Función1, con esta función aplicada al último.

entonces debes escribir

scala> val ummThenAhem = (addAhem _).compose(addUmm _) ummThenAhem: String => java.lang.String = <function1>

para tratar addAhem y addUmm como funciones parcialmente aplicadas (es decir, function1 )

scala> addAhem _ res0: String => java.lang.String = <function1>


addAhem es un método. compose método de compose se define en las funciones. addAhem _ convierte addAhem del método en función, por lo que se puede addAhem a compose en él. compose espera una función como argumento. Le está dando un método addUmm convirtiendo addUmm en una función con addUmm _ (El guión bajo puede addUmm _ porque el compilador puede convertir automáticamente un método en una función cuando sabe que una función se espera de todos modos). Entonces tu código:

addAhem _ compose addUmm

es lo mismo que

(addAhem _).compose(addUmm)

pero no

addAhem(_).compose(addUmm(_))

PD. No miré el enlace que proporcionaste.