Seguimos con scala : https://emanuelpeg.blogspot.com/2019/09/funciones-con-funciones-como-parametros.html
Cuando pasamos un función por parámetro Scala infiere el tipo de la función y lo chequea con el tipo esperado, esto no es más que el chequeo por tipo que realiza cualquier lenguaje de tipado estático.
Veamos un ejemplo:
valueAtOneQuarter((x: Double) => 3 * x) // 0.75
Dado que la función valeAtOneQuarter espera un (Doble) => Doble por lo tanto Scala puede inferir que es un double y de esta manera podemos escribir :
valueAtOneQuarter((x) => 3 * x)
También podemos quitar los paréntesis :
valueAtOneQuarter(x => 3 * x)
También podemos utilizar azúcar sintáctica, dado que la variable x no representa algo en particular y no hay muchas lógica aquí :
valueAtOneQuarter(3 * _)
De esta manera, como la función tiene el tipo declarado Scala lo puede inferir pero si nosotros hacemos :
val fun = 3 * _
Vamos a tener un error dado que no se puede inferir el tipo, pero esto se puede soluciónar así :
val fun = 3 * (_: Double)
o
val fun: (Double) => Double = 3 * _
Especificar el tipo de _ es útil para convertir los métodos en funciones. Por ejemplo, (_: String) .length es una función String => Int, y (_: String) .substring (_: Int, _: Int) es una función (String, Int, Int) => String.