Scala Language
Funciones
Buscar..
Observaciones
Scala tiene funciones de primera clase.
Diferencia entre funciones y métodos:
Una función no es un método en Scala: las funciones son un valor y pueden asignarse como tales. Los métodos (creados usando def
), por otro lado, deben pertenecer a una clase, rasgo u objeto.
- Las funciones se compilan en una clase que extiende un rasgo (como
Function1
) en tiempo de compilación, y se crean instancias a un valor en tiempo de ejecución. Los métodos, por otro lado, son miembros de su clase, rasgo u objeto, y no existen fuera de eso. - Un método se puede convertir en una función, pero una función no se puede convertir en un método.
- Los métodos pueden tener parametrización de tipo, mientras que las funciones no.
- Los métodos pueden tener valores predeterminados de parámetros, mientras que las funciones no pueden.
Funciones anónimas
Las funciones anónimas son funciones que están definidas pero no se les asigna un nombre.
La siguiente es una función anónima que toma dos enteros y devuelve la suma.
(x: Int, y: Int) => x + y
La expresión resultante se puede asignar a un val
:
val sum = (x: Int, y: Int) => x + y
Las funciones anónimas se utilizan principalmente como argumentos para otras funciones. Por ejemplo, la función de map
en una colección espera otra función como argumento:
// Returns Seq("FOO", "BAR", "QUX")
Seq("Foo", "Bar", "Qux").map((x: String) => x.toUpperCase)
Los tipos de los argumentos de la función anónima se pueden omitir: los tipos se deducen automáticamente :
Seq("Foo", "Bar", "Qux").map((x) => x.toUpperCase)
Si hay un solo argumento, se pueden omitir los paréntesis alrededor de ese argumento:
Seq("Foo", "Bar", "Qux").map(x => x.toUpperCase)
Subraya la taquigrafía
Hay una sintaxis aún más corta que no requiere nombres para los argumentos. El fragmento anterior se puede escribir:
Seq("Foo", "Bar", "Qux").map(_.toUpperCase)
_
representa los argumentos de la función anónima en posición. Con una función anónima que tiene múltiples parámetros, cada aparición de _
se referirá a un argumento diferente. Por ejemplo, las dos expresiones siguientes son equivalentes:
// Returns "FooBarQux" in both cases
Seq("Foo", "Bar", "Qux").reduce((s1, s2) => s1 + s2)
Seq("Foo", "Bar", "Qux").reduce(_ + _)
Al usar esta abreviatura, cualquier argumento representado por la posición _
solo puede ser referenciado una sola vez y en el mismo orden.
Funciones anónimas sin parámetros
Para crear un valor para una función anónima que no toma parámetros, deje la lista de parámetros en blanco:
val sayHello = () => println("hello")
Composición
La composición de funciones permite que dos funciones funcionen y se vean como una sola función. Expresado en términos matemáticos, dada una función f(x)
y una función g(x)
, la función h(x) = f(g(x))
.
Cuando se compila una función, se compila a un tipo relacionado con Function1
. Scala proporciona dos métodos en la Function1
aplicación relacionada a la composición: andThen
y compose
. El método de compose
encaja con la definición matemática anterior así:
val f: B => C = ...
val g: A => B = ...
val h: A => C = f compose g
El andThen
(piensa que h(x) = g(f(x))
) tiene una sensación más parecida a DSL:
val f: A => B = ...
val g: B => C = ...
val h: A => C = f andThen g
Se asigna una nueva función anónima que se cierra sobre f
y g
. Esta función está vinculada a la nueva función h
en ambos casos.
def andThen(g: B => C): A => C = new (A => C){
def apply(x: A) = g(self(x))
}
Si cualquiera de f
o g
funciona a través de un efecto secundario, llamar a h
hará que todos los efectos secundarios de f
y g
ocurran en el pedido. Lo mismo ocurre con cualquier cambio de estado mutable.
Relación a funciones parciales
trait PartialFunction[-A, +B] extends (A => B)
Cada-solo argumento PartialFunction
es también un Function1
. Esto es contraintuitivo en un sentido matemático formal, pero se ajusta mejor al diseño orientado a objetos. Por esta razón, Function1
no tiene que proporcionar un método true
isDefinedAt
constante.
Para definir una función parcial (que también es una función), use la siguiente sintaxis:
{ case i: Int => i + 1 } // or equivalently { case i: Int ⇒ i + 1 }
Para más detalles, eche un vistazo a PartialFunctions .