lunes, 9 de enero de 2017

Un resumen de Scala for the Impatient, parte 6


Funciones. 

Scala tiene funciones además de métodos. La diferencia es que las funciones no pertenecen a ningún objeto.
Para definir una función solo es necesario, nombre, parámetros y el cuerpo de la función:

def abs(x: Double) = if (x >= 0) x else -x

No es necesario definir el tipo, dado que el compilador lo infiere. En el caso que no pueda inferirlo como funciones recursivas, se le debe indicar.

Si la función debe hacer varias cosas se puede utilizar las llaves:

def fac(n : Int) = {
    var r = 1
    for (i <- 1 to n) r = r * i
     r
}

La función retorna lo ultimo que se ejecuta y no es necesario la palabra return.

Se pueden utilizar valores por defecto para las funciones:

def decorate(str: String, left: String = "[", right: String = "]") =
         left + str + right

Si llamamos a decorate("Hello") , el resultado va a ser :  "[Hello]"
Si llamamos a decorate("Hello", ">>>[") el resultado va a ser : ">>>[Hello]", pero, ¿como podemos llamar a la función con un parámetro para rigth y el default para left? con los parámetros nombrados:

decorate("Hello", right = "]<<<") // Calls decorate("Hello", "[", "]<<<")

Podemos nombrar todos los parámetros:

decorate(left = "<<<", str = "Hello", right = ">>>")

El resultado es "<<<Hello>>>" . Note que el orden de los parámetros no eran iguales que como fueron definidos.

Algunas veces es necesario implementar funciones con un numero variable de parametros, esto se hace con el * :

def sum(args: Int*) = {
    var result = 0
    for (arg <- args) result += arg
    result
}

Y esto se puede llamar de la siguiente manera:

val s = sum(1, 4, 9, 16, 25)
La función recibe un parámetro de tipo Seq pero no podemos pasar una sequencia desde una función por ejemplo esto retornara error:

val s = sum(1 to 5) // Error

Si la función es llamada con un solo argumento este debe ser entero y no rango de enteros, para solucionar este problema se debe agregar _* :

val s = sum(1 to 5: _*) // Consider 1 to 5 as an argument sequence

Si necesitamos llamar a una función recursiva podemos utilizar el mismo artilugio:

def sum(args: Int*) : Int = {
   if (args.length == 0) 0
   else args.head + recursiveSum(args.tail : _*)
}