Funciones
## Objetivos de Aprendizaje
- Dominar definiciones de funciones con def
- Comprender parametros de funciones y tipos de retorno
- Aprender recursion
- Trabajar con funciones anonimas
- Comprender closures y aplicaciones parciales
## Basicos de Funciones
### Definiendo Funciones
```scala
def greet(): String = {
"Hello, World!"
}
println(greet()) // Hello, World!
```
### Funcion con Parametros
```scala
def add(a: Int, b: Int): Int = {
a + b
}
println(add(3, 5)) // 8
```
### Inferencia del Tipo de Retorno
Scala puede inferir tipos de retorno para expresiones:
```scala
def add(a: Int, b: Int) = a + b // Tipo de retorno inferido como Int
def greet() = "Hello" // Tipo de retorno inferido como String
```
### Tipo de Retorno Unit
```scala
def printSum(a: Int, b: Int): Unit = {
println(s"Sum: ${a + b}")
}
printSum(3, 5) // Sum: 8
```
## Tipos de Parametros
### Parametros por Defecto
```scala
def greet(name: String = "World") = s"Hello, $name!"
greet() // Hello, World!
greet("Alice") // Hello, Alice!
```
### Argumentos Nombrados
```scala
def connect(host: String = "localhost", port: Int = 8080) = {
s"$host:$port"
}
connect(port = 9000, host = "server") // server:9000
```
### Argumentos Variables (Varargs)
```scala
def sum(numbers: Int*): Int = {
numbers.sum
}
sum(1, 2, 3, 4, 5) // 15
sum(1, 2, 3) // 6
```
### Grupos de Parametros
```scala
def addAndMultiply(a: Int)(b: Int)(c: Int): Int = {
(a + b) * c
}
addAndMultiply(1)(2)(3) // 9
```
## Recursion
### Recursion Basica
```scala
def factorial(n: Int): BigInt = {
if (n <= 1) 1
else n * factorial(n - 1)
}
factorial(5) // 120
```
### Recursion de Cola
Las funciones tail-recursive se optimizan para evitar desbordamiento de pila:
```scala
def factorialTail(n: Int): BigInt = {
@annotation.tailrec
def loop(acc: BigInt, n: Int): BigInt = {
if (n <= 1) acc
else loop(acc * n, n - 1)
}
loop(1, n)
}
factorialTail(10000) // Funciona sin desbordamiento de pila
```
### Recursion Mutua
```scala
def isEven(n: Int): Boolean =
if (n == 0) true else isOdd(n - 1)
def isOdd(n: Int): Boolean =
if (n == 0) false else isEven(n - 1)
isEven(10) // true
```
## FuncionesAnonimas
### Sintaxis Basica
```scala
val addOne = (x: Int) => x + 1
addOne(5) // 6
```
### Multiples Parametros
```scala
val add = (a: Int, b: Int) => a + b
add(3, 5) // 8
```
### Sin Parametros
```scala
val getTime = () => System.currentTimeMillis()
getTime()
```
### Sintaxis de Marcador de Posicion
```scala
val numbers = List(1, 2, 3, 4, 5)
numbers.map((x: Int) => x * 2)
numbers.map(x => x * 2)
numbers.map(_ * 2) // Marcador de posicion para un solo parametro
val add = (_: Int) + (_: Int) // Multiples marcadores
add(3, 5) // 8
```
## Funciones de Orden Superior
Funciones que toman funciones como parametros o devuelven funciones:
```scala
def applyTwice(f: Int => Int, x: Int): Int = {
f(f(x))
}
def double(x: Int) = x * 2
applyTwice(double, 5) // 20 (5 * 2 * 2)
```
### Funciones como Valores de Retorno
```scala
def multiplier(factor: Int): Int => Int = {
(x: Int) => x * factor
}
val triple = multiplier(3)
triple(5) // 15
```
## Closures
Un closure es una funcion que captura variables de su scope externo:
```scala
var factor = 10
val multiply: Int => Int = (x: Int) => x * factor
multiply(5) // 50
factor = 20
multiply(5) // 100 (el closure ve el nuevo valor)
```
## Currying
### Funciones Curried
```scala
def curriedSum(a: Int)(b: Int): Int = a + b
curriedSum(3)(5) // 8
val addFive = curriedSum(5) _
addFive(3) // 8
```
### Por que Currying?
```scala
def withTimestamp(log: String => Unit)(message: String): String = {
val timestamp = System.currentTimeMillis()
log(s"[$timestamp] $message")
message
}
def logToConsole(msg: String) = println(msg)
def logToFile(msg: String) = /* escribir a archivo */ ()
val timestampedLog = withTimestamp(logToConsole) _
timestampedLog("Hello") // [1234567890] Hello
```
## Sintaxis Especial de Funciones
### Notacion Infija
```scala
object Math {
def +(a: Int, b: Int): Int = a.+(b)
def -(a: Int, b: Int): Int = a.-(b)
}
```
### Operadores como Metodos
```scala
val list = List(1, 2, 3, 4, 5)
list.fold(0)(_ + _) // 15
list.foldLeft(0)(_ + _) // Igual
(0 /: list)(_ + _) // Igual (foldLeft con operador /:)
```
## Metodo vs Funcion
### Definicion de Metodo
```scala
object Calculator {
def add(a: Int, b: Int): Int = a + b
}
```
### Convertir Metodo a Funcion
```scala
val addFunction: (Int, Int) => Int = Calculator.add _
addFunction(3, 5) // 8
```
## Resumen
- Usa `def` para definir funciones
- Los parametros tienen tipos explicitos; los tipos de retorno pueden ser inferidos
- Parametros por defecto y argumentos nombrados aumentan la flexibilidad
- Varargs (`_*`) aceptan numero variable de argumentos
- La recursion es fundamental en programacion funcional; usa recursion de cola para eficiencia
- Las funciones anonimas proporcionan literales de funcion concisos
- Las funciones de orden superior toman o devuelven funciones
- Los closures capturan variables del entorno
- El currying divide funciones de multiples parametros en cadenas de parametros simples
- Los metodos se definen en clases/objetos; las funciones son valores
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →