Hablar de funciones puede parecer intimidador si pensamos en términos matemáticos complejos, pero en realidad es un concepto sencillo y poderoso que trasciende al ámbito de la programación. Al entender una función, pensamos en dos elementos clave: el dominio y el rango. El dominio se refiere a todo lo que puede entrar a la función, es decir, los valores que puede aceptar como entrada. El rango, por su parte, abarca todos los posibles resultados que la función puede producir, es decir, sus salidas. El papel central de una función es transformar datos de entrada en resultados de salida, mapeando un dominio hacia un rango.
¿Cómo se crean funciones en Scala?
Scala, al ser un lenguaje multiparadigma, permite expresar funciones de formas muy variadas y flexibles. Aquí exploramos cómo definir una función básica en Scala y algunas de sus variantes:
Definición básica de una función:
def f(x:Int):Int= x * x
Esta función f toma un entero x como argumento y retorna el cuadrado de x. El símbolo = indica la transformación de entrada a salida. La expresión puede ser tan compleja o simple como se desee.
Función anónima:
Una función anónima es una función que no tiene un nombre específico. En Scala, se puede representar usando una sintaxis de flecha:
(x:Int)=> x * x
Esta sintaxis es similar a las Arrow Functions en JavaScript. Las funciones anónimas se pueden asignar a variables para reutilizarlas:
val a =(x:Int)=> x * x
Con esto, a(2) o a(4) produce el mismo resultado que la función f previamente definida.
¿Qué son las funciones de orden superior?
Las funciones de orden superior son aquellas que pueden aceptar otras funciones como argumentos o retornar funciones. Esto es posible porque las funciones se tratan como valores primero-clase, permitiéndoles ser pasadas alrededor igual que otros tipos de datos, como enteros o cadenas.
Ejemplo de función de orden superior:
def g(h:Int=>Int)= h(3)
Aquí, g es una función que toma otra función h como argumento. h debe aceptar un entero y devolver un entero. Al ejecutarse, g llamará a h con el número 3.
¿Cómo funciona el currying en Scala?
El currying es una característica que permite transformar una función que toma múltiples argumentos en una secuencia de funciones que toma un único argumento. Esto puede ser muy útil en la construcción de funciones más complejas a partir de funciones más simples o para facilitar la reutilización de funciones.
Ejemplo de currying:
def k(h:Int=>Int)(x:Int):Int= h(x)
Esta función k toma dos argumentos en dos grupos distintos: una función h y un entero x. La ejecución de k requiere aplicar ambos argumentos de forma secuencial.
¿Cómo se tratan las funciones como objetos en Scala?
En Scala, incluso las funciones pueden ser tratadas como objetos. La notación apply se usa para llamar funciones cuando son objetos, y es posible convertir una función de manera explícita a un objeto. Si una función no es un objeto, intentará convertirse automáticamente cuando se llama a sus métodos.
Convertir una función en un objeto:
val c = f _
Aquí _ indica al compilador que queremos tratar f como un objeto, haciendo posible llamarlo como c.apply(2).
¿Cómo definir métodos dentro de objetos?
Las funciones en Scala pueden también estar encapsuladas en objetos, en cuyo caso comúnmente se les llama métodos. Esto es parte de la integración de los paradigmas de programación funcional y orientada a objetos de Scala.
Creación de un método:
object Util {def metodo(x:Int):Int= x + x
val a = metodo _
}Util.metodo(3)// Resulta en 6
El método metodo se define dentro del objeto Util, y a es una referencia al metodo, que de este modo puede ser utilizado como función.
Algunos conceptos pueden parecer desalentadores al principio, pero con práctica y exploración, se vuelve cada vez más fácil comprender y aplicar estas herramientas en distintos contextos dentro de la programación en Scala. Explora, equivócate y experimenta sin miedo: esa es la mejor forma de aprender. Y recuerda, recientemente exploramos cómo programar funciones que generan otras funciones, lo cual era el reto al final de la clase. ¡Anímate a intentarlo!
Según entiendo sería algo así 🤯
def isGreater(a: Int) = (b: Int) => a < b
println(isGreater(10)(20))
nice!
from your code:
def isGreater(a:Int):Int=>Boolean={(b:Int)=> a < b
}val f =isGreater(10)f(20)
Hola!
def isGreather(x:Int,y:Int):Boolean={ x > y
}val isGreatherObj = isGreather _
def comparar(fx:(Int,Int)=>Boolean,a:Int,b:Int):Boolean=fx(a,b)comparar(isGreatherObj,3,1)
Loco me confundí en los dos puntos de la función compare cuando la declaras antes del bool
Mi solucion es generar una funcion que retorne una funcion anonima y en la funcion anonima se "fija" el parametro pasado a la funcion padre. El concepto puede ser dificil de explica, pero si miras el codigo seguro lo entiendes.
// Funcion que genera funciones
def isGreaterGenerator(ref: Int): Int => Boolean = {
(x:Int) => ref < x
}
// Usando el generador de funciones
val isGreaterThanTen = isGreaterGenerator(10)
// Usando la funcion generada
isGreaterThanTen(11) // true
isGreaterThanTen(1) // false
isGreaterThanTen(10) // false
@briggizade Esta pregunta es bastante interesante.
Para empezar, hay que recordar que aunque Scala y Java funcionan sobre la JVM, eso no significa que Scala tenga que usar las interfaces de Java; algunas veces sí, pero no en todos los casos (y este no es uno de esos).
Cuando miramos la especificación del lenguaje acerca de las funciones anónimas, se puede ver que la definición de una función anónima no tiene una relación con la interfaz Function de java, si no con la familia de traits scala.FunctionN
Y con respecto a la salida que "no devuelve nada", recuerda que en Scala no existe esa posibilidad, siempre se va a retornar algo, y cuando no queremos retornar algo en particular, se retorna Unit.
PD: ¿Te fijaste cuántos tratis de FunctionN hay?, la verdad es que no son infinitos, y el límite que tienen está dado por restricciones de la JVM.
PD2: ¿Te fijaste cómo es el caso con los traits, no de Funciones, si no de las Tuplas? ;)
Yo no le tengo miedo a las mates :D
Funciones
Para definir funciones en scala tenemos dos opciones
def f(x: Any) = // Código ...
a = (x: Any) => // Código ...
La segunda siendo una función lambda la cual se comporta como un objeto y podemos usar el metodo apply. Podemos pasar de una funciún común a un obeto usando la siguiente expresión
val c = f _
Lo cual deja c como una función lambda basada en f. Para definir funciones que reciben funciones como parametros usamos la siguiente expresión
La segunda notación nos permiten pasar dos parametros a la función k, en primer lugar otra función y en segundo lugar una variable.
Funciones como metodos
object Util{ def metodo(x:Int)= x+x
val a = metodo _
}
Tengo dos soluciones pero entonces no se cual seria la que mejor da la repsuesta al reto:
SOLUCION 1:
scala> def calcMayorQue(x:Int,y:Int)={|if(x>y){|"El numero "+ x +" es mayor al numero "+ y}|else{|"El numero "+ x +" es menor al numero "+ y}}calcMayorQue:(x:Int,y:Int)Stringscala>calcMayorQue(5,8)res1:String=El numero 5 es menor al numero 8
SOLUCION 2:
scala> def calcMayorQue(x:Int,y:Int)={| val resComp = x > y
| def MayorQue(bool:Boolean)={|if(bool){|"El numero "+ x +" es mayor al numero "+ y}|else{|"El numero "+ x +" es menor al numero "+ y}}|MayorQue(resComp)}calcMayorQue:(x:Int,y:Int)Stringscala>calcMayorQue(5,1)res2:String=El numero 5 es mayor al numero 1
Quedo atento a sus comentarios
Funciones
Hablamos de funciones en su definición matemática.
Dominio: Datos de entrada
Rango: Datos de salida
f: D → R
Funciones de orden superior
Una función es tratada como un valor más. Esto implica que una función puede recibir y retornar otras funciones.
Funciones anónimas (lambdas)
Funciones como objetos
Funciones como métodos
def f(x:Int)= x * x
// f: (x: Int)Intf(2)//res0: Int = 4f(2)//res1: Int = 16// Función anónima(x;Int)=> x*x
// res2: Int => Int = $$Lambda$$770/123467@333f5f6val a =(x;Int)=> x*x
//a: Int => Int = $$Lambda$$770/123467@333f5f6a(2)//res3: Int = 4a(4)//res4: Int = 16// a es un objeto y f es una funciónf.apply(2)// errora.apply(2)////res4: Int = 4// convertir f en objetoval c = f _
// c: Int => Int = $$Lambda$$770/123467@333f5f6c.apply(2)//res7: Int = 4def g(h:Int=>Int)= h(3)//g: h: Int => Int)Intg(f)//res10: Int =9def k(h:Int=>Int)(x:Int)= h(x)// k: (h: Int => Int)(x: Int)Intk(f)(3)//res11: Int = 9k(f)(4)//res12: Int = 16// Funciones como métodosobject Util {def metodo(x:Int)= x+x
val a = metodo _
}Util.metodo(3)//res5: Int = 6Util.a(3)//res6: Int = 6
En mi caso si me funciono f.apply() sobre
def f(x:Int)= x * x
:o
scala> val otraFunction = (parametro: Int) => ((x: Int) => x > parametro)
otraFunction: Int => (Int => Boolean) = $$Lambda$992/0x00000008010dc040@53c1f4ae
scala> otraFunction(10)(5)
res18: Boolean = false
scala> otraFunction(10)(13)
res19: Boolean = true
Hola, yo encounter otra manera para pasar los paramteros de las funciones
// Definicion de la function suma para hacer el llamado se ejecuta como fx_suma(3,4)def fx_suma(x:Int,y:Int):Int={ x+y
}// Convertir la function en un objetoval obj_fx_suma = fx_suma _
def fx_multi(x:Int,y:Int):Int={ x*y
}// Definicion de una funcion de orden superiordef fx_orden_superior(fx:(Int,Int)=>Int,x:Int,y:Int):Int={fx(x,y)}// Llamado con la funcion como objetofx_orden_superior(obj_fx_suma,3,5)fx_orden_superior(fx_suma,3,5)fx_orden_superior(fx_multi,3,5)
me dio mucha risa cuando dijiste: existe una **vaina **que se llama el apply jaja
Yo entendí algo así: def fun() = (x = (num: Int) => num > 3)
Prueba
Hola para el desarrollo del reto he planteado el siguiente codigo, no me da error pero tampoco obtengo un resultado apesar de que le dije que retornara un string
def fx_identify_parameter(param:Int)={ def validator():String={ val num_aleatorio = scala.util.Random.nextInt(10)if(num_aleatorio > param){"El parametro es mayor al numero aleatorio"}elseif(num_aleatorio < param){"El parametro es menor al numero aleatorio"}else{"El parametro es igual al numero aleatorio"}}}```
En el código que hiciste, la función fx_identify_parameter no tiene un valor de retorno. Internamente definiste una función validator que sí devuelve un String, pero esta función nunca se llama, solo se define.
Si llamas esta función validator al final de la función fx_identify_parameter, eso debería darte el resultado que esperas.
También quisiera notar que a nivel de estilo de cómo nombrar las funciones, en Scala usar camelCase es la manera sugerida (diferente a python, donde el estilo sugiere usar snake_case). Si te da curiosidad, la documentación de Scala tiene una sección explicando esto en detalle: https://docs.scala-lang.org/style/naming-conventions.html
Si, profe mil gracias, efectivamente lo que faltaba era llamar la función, con los siguientes videos del curso pude resolverlo
def fxIdentifyParameter(param:Int):String={ def validator():String={ val num_aleatorio = scala.util.Random.nextInt(10)if(num_aleatorio > param){"El parametro es mayor al numero aleatorio"}elseif(num_aleatorio < param){"El parametro es menor al numero aleatorio"}else{"El parametro es igual al numero aleatorio"}}validator()}
La ejecución termino exitosa, y me di cuenta que al estar la función inmersa en la otra no era necesario enviarle el parametro param por que esta ya la reconocia,
scala>fxIdentifyParameter(5)res10:String=El parametro es menor al numero aleatorio
Mil gracias por el tip del nombramiento de las funciones y por tan buen curso
el mio quedo
scala> def mayorNumero(a: Int, b: Int): Int = {
| if (a > b) a
| else b
| }
def mayorNumero(a: Int, b: Int): Int
scala>
scala> val num1 = 8
val num1: Int = 8
scala> val num2 = 12
val num2: Int = 12
scala> val mayor = mayorNumero(num1, num2)
val mayor: Int = 12
Alguien podría ayudarme a ver donde está el error por favor?:
Según entiendo puedo tener estas dos soluciones y me retornan el Boolean
def greaterT(x: Int)(y: Int) = y > x
def greaterThan(x: Int, y:Int) = x > y
Me gusta que las matemáticas están implicitas en el lenguaje.
Mi solución:
def isGreaterThan(compareValue:Int)(value:Int):Boolean = compareValue < value
y ahora simplemente generamos las funciones o ejecutamos directamente:
val isGreaterThan5 = isGreaterThan(5)
isGreaterThan5(3) // false
isGreaterThan5(6) // true
isGreaterThan(10)(7) // false
Solucion:
val evaluaSiEsMayor = (paramIngresado: Int, paramExistente: Int) => if(paramExistente > paramIngresado) "El numero existenete es mayor al ingresado" else "El numero existente es menor o igual al numero ingresado"