¿Qué es la programación funcional y por qué es importante?
La programación funcional es un paradigma que se centra en utilizar funciones matemáticas puras para manejar datos y procesos efectivos. Es fundamental en ciertos contextos debido a su habilidad para abstraer problemas complejos, facilitando su resolución eficiente. La importancia de la programación funcional radica en su capacidad para tratar los datos de manera uniforme, asegurando que el flujo de información sea claro y predecible.
Entre sus ventajas destacadas están:
Reducción de efectos secundarios.
Mayor capacidad para reutilizar código.
Mejora en la depuración y el mantenimiento.
Facilita la programación concurrente.
¿Cómo funciona el pattern matching en programación funcional?
El pattern matching o emparejamiento de patrones es una herramienta poderosa dentro de la programación funcional que simplifica el proceso de verificar y desglosar estructuras de datos. Este esquema permite comparar datos con diferentes patrones y ejecutar acciones en función de si el patrón esperado es encontrado.
Ejemplo básico con strings
Supongamos que tenemos un string y queremos identificar si coincide con ciertos patrones. Podemos implementar este patrón con una estructura como esta:
val stringPattern ="hola"match{case"mundo"=>"00"case"hola"=>"a a"}
Esta estructura verifica si el string coincide con "hola" y devuelve "a a" como resultado.
Ejemplo avanzado con listas
El pattern matching es flexible y se puede utilizar para trabajar con listas y otros tipos de datos compuestos. Por ejemplo, supongamos que deseamos sumar los elementos en una lista específica:
def g(x: List[Int]):Int= x match{case List(a, b, c)=> a + b + c
case List(a, b, c, d)=> a + b + c + d
case _ =>0}
En este caso, estamos verificando diferentes patrones en listas con tres o cuatro elementos, y devolviendo la suma de estos si cumplen con el patrón.
¿Cómo podemos utilizar el pattern matching con case classes?
Los case classes son estructuras de datos que se benefician de la versatilidad del pattern matching. Su uso es común cuando se desean manejar instancias de datos estructurados, como en el siguiente ejemplo:
Emparejamiento de patrones en case classes
Creemos una case class de tipo Persona y empecemos a emparejar:
caseclass Persona(nombre:String, edad:Int)val p1 = Persona("María",20)val p2 = Persona("Freddy",15)def h(x: Persona):String= x match{case y if y.edad >18=>"Mayor de edad"case _ =>"No es mayor de edad"}
En este ejemplo, se verifica si la edad de una persona es mayor de 18, utilizando un if dentro del emparejamiento para aplicar condiciones específicas.
Desafío: Modificar el emparejamiento con condiciones adicionales
Te invito a mejorar este último ejemplo modificando la función h para aportar una lógica más elaborada. Intenta modificar el código para que, si la persona se llama María pero es menor de edad, se dé una respuesta diferente a la que se daría si fuera mayor de edad, o si se tratara de otro nombre.
Ejemplo modificado:
def h(x: Persona):String= x match{case Persona("María", edad)if edad <18=>"María menor de edad"case Persona("María", _)=>"María mayor de edad"case y if y.edad >18=>"Mayor de edad"case _ =>"No es mayor de edad"}
Más allá de los conceptos básicos
La capacidad del pattern matching va más allá de lo básico. Puede definir comportamientos específicos y trabajar con datos complejos de manera más simple y eficiente. Para seguir ampliando tus conocimientos, te animo a explorar nuevas formas de utilizar la programación funcional en diferentes contextos, aprovechando al máximo sus técnicas avanzadas. Continúa desafiándote con ejercicios y proyectos prácticos, y verás cómo este paradigma puede transformar tu enfoque hacia la programación. ¡Adelante, sigue aprendiendo!
caseclassPersona(nombre:String,edad:Int)val p1 =Persona("Maria",20)val p2 =Persona("Freddy",15)def h(x:Persona)= x match {case y if y.nombre=="Maria"&& y.edad>=18=>"Esta Maria es mayor de edad"case y if y.nombre=="Maria"&& y.edad<=18=>"Esta Maria es menor de edad"case y if y.edad>=18=>"Mayor de edad"case_=>"No es mayor de edad"}```
Buen aporte
val p1 =Person("maria",15)val p2 =Person("maria",28)val p3 =Person("diana",25)def h(x:Person)= x match {case x if x.nombre=="maria"&& x.edad>=18=>"Puedes entrar a la disco Maria"case x if x.nombre=="maria"&& x.edad<18=>"Lo siento, no puedes entrar a la disco Maria"case _ =>"SoloMarias"}
"Solo Marias" jajaja like!
Creo que sería mejor que enseñará a desarrollar usando siempre nombres de variables y funciones claros y legibles, no h o x
Mi solución al reto:
// Modelscaseclass Person(name:String,age:Int)// Dataval vip_people_name = List("Maria")val people = List( Person("Amanda",16), Person("Betsabet",42), Person(vip_people_name(0),16), Person(vip_people_name(0),31))// Constantsval AGE_OF_MAJORITY =18// Utilsdef checkHasMajority(age:Int)= age >= AGE_OF_MAJORITY
//Controllersdef getPersonValidated(person:Person,vip_people_name:List[String])={val isVip = vip_people_name.contains(person.name)val hasMajority = checkHasMajority(person.age) person match{case selected if hasMajority && isVip => selected.name +" es mayor de edad y es VIP"case selected if!hasMajority && isVip => selected.name +" es menor de edad pero es VIP"case selected if hasMajority => selected.name +" es mayor de edad"case _ => person.name +" no es mayor de edad"}}// Viewsdef presenter(validatedPeople:List[String])={ println("---------------------") validatedPeople.map(personValidated=> println(personValidated)) println("---------------------")}// Rendering viewpresenter(people.map((person)=>getPersonValidated(person,vip_people_name)))
Mi solución al reto:
Hola, en mi caso me mostro esto:
caseList(a, b, c, d)=> a + b + c + d
|^^^|value + is not a member ofAny, but could be made available as an extension method.||Oneof the following imports might make progress towards fixing the problem:||import math.Fractional.Implicits.infixFractionalOps|import math.Integral.Implicits.infixIntegralOps|import math.Numeric.Implicits.infixNumericOps|
val p1 = Persona("Maria", 20)
val p2 = Persona("Pedro", 20)
val p3 = Persona("Pablo", 16)
val p4 = Persona("Pablo", 20)
def h(x: Persona) = x match {
| case y if y.nombre == "Pablo" && y.edad >= 18 => "Este Pablo es mayor de edad"
| case y if y.nombre == "Pablo" && y.edad <= 18 => "Este Pablo es menor de edad"
| case y if y.edad >= 18 => "Mayor de edad"
| case _ => "No es mayor de edad"
| }
object Main {def main(args: Array[String]):Unit={val p1 = Person("maria",15)val p2 = Person("maria",28)val p3 = Person("diana",25) print(s"${isAdult(p1)}, ${isAdult(p2)}, ${isAdult(p3)}")}}caseclass Person(nombre:String, edad:Int)def isAdult(person: Person):String= person match{// en este caso p no es "comparable" sino que es una variable local para hacer la comparacion, toma el valor de personcase p
if p.nombre =="maria"&& p.edad >=18=>"Mayor de edad"case p
if p.nombre =="maria"&& p.edad <18=>"Menor de edad"case _ =>"No eres Maria"}
Encontrando patrones
En programación funcional la herencia no suele ser tan importante como en OOP, pero la forma de los datos suele importar mucho más.
Similar a un switch de otros lenguajes, nor permite definir casos de emparejamiento. Puede usarse como una alternativa al if, pero es mucho más potente.
"hola"match{case"mundo"=>"oo"case"hola"=>"aa"}// res: String = aadef g(x: Seq[Int])= x match{case List(a, b, c)=> a + b + c
case List(a, b, c, d)=> a + b + c + d
case _ =>0}g:(x: Seq[Int])Intg(Seq(1,1,1))// res1: Int = 3g(Seq(1,1))// res1: Int = 0caseclass Persona(nombre:String, edad:Int)val p1 = Persona("Maria",20)val p2 = Persona("Fredy",15)def h(x: Persona)= x match{case y if y.edad >=18=>"Mayor de edad"case _ =>"No es mayor de edad"}h(p1)// res: String = Mayor de edadh(p2)// res: String = No es mayor de edad
caseclasspersona(nombre:String,Edad:Int)val p1 =persona("Maria",20)val p2 =persona("Maria",15)val p3 =persona("Fredy",16)def h(x: persona)= x match {case y if y.nombre== x.nombre=>"T" match {case"T"if y.Edad>=18=>"Es mayor de edad"case_=>"No es mayor de edad"}case z if z.nombre!= x.nombre=>"F" match {case"F"if z.Edad>=18=>"Es mayor de edad"case_=>"No es mayor de edad"}}h(p1)h(p2)h(p3)
Resultado:
val res0: String = Es mayor de edad
val res1: String = No es mayor de edad
val res2: String = No es mayor de edad
def h(x:Persona)= x match {casePersona("Maria", a)if a >=18=>"Maria eres mayor de edad"casePersona("Maria", a)if a <18=>"Maria no eres mayor de edad"case y if y.edad>=18=>"Mayor de edad"case_=> "No es mayor de edad
}
def h(x:Persona)= x match {case y if y.edad>=18&& y.nombre!="Maria"=>"Mayor de edad"case y if y.edad>=18&& y.nombre=="Maria"=>"Se llama Maria y es mayor de edad"case y if y.edad<18&& y.nombre=="Maria"=>"Se llama Maria y es menor de edad"case_=>"Menor de edad"}
scala> def h(x:Persona)= x match {|case y if y.nombre.equals("Maria")=> y match {|case z if z.edad>=18=>"Maria ya eres grandecita"|case _ =>"Maria eres aun una niña"|}|case _ =>"Otra persona"|}h:(x:Persona)Stringscala>h(p1)res6:String=Maria ya eres grandecita
scala>h(p2)res7:String=Otra persona
scala>h(Persona("Maria",13))res8:String=Maria eres aun una niña
Reto
Reto:
Mi solución al reto
object Eval {
case class Persona(nombre: String, edad: Int)
def edad(x: Int) : String = if (x > 18) "Mayor de edad" else "No es mayor de edad"
def h(x: Persona) : String = x match {
case Persona ("Maria", ) => "Es Maria y " + edad (x.edad)
case Persona (, _) => "No es Maria y " + edad (x.edad)
}
}
val p1 = Eval.Persona("Maria", 20)
val p2 = Eval.Persona("Fredy", 15)
Eval.h(p1)
Eval.h(p2)
scala>caseclassPostulante(nombre:String,edad:Int,ponderado:Int);defined classPostulantescala> val pstl1 =Postulante("Maria",15,19);pstl1:Postulante=Postulante(Maria,15,19)scala> val pstl2 =Postulante("Maria",20,17);pstl2:Postulante=Postulante(Maria,20,17)scala> val pstl3 =Postulante("Juan",20,11);pstl3:Postulante=Postulante(Juan,20,11)scala> def Reto(pstl:Postulante)= pstl match{|case y if pstl.nombre=="Maria"&& pstl.edad>=18=> pstl.nombre+" es Mayor de Edad"|case z if pstl.nombre=="Maria"&& pstl.edad<18=> pstl.nombre+" es Menor de Edad"|case _ =>"No es Maria!"|}Reto:(pstl:Postulante)Stringscala>Reto(pstl1);res0:String=Maria es Menor de Edadscala>Reto(pstl2);res1:String=Maria es Mayor de Edadscala>Reto(pstl3);res2:String=No es Maria!
def response(p:Person)= p match {|casePerson("Maria",_)if p.age>=18=>"Hola Maria ya eres mayor de edad"|case r if r.age>=18=> s"Hola ${r.name} ya eres mayor de edad"|case_=> s"Hola ${p.name} eres baby todavia"|}
Aqui esta mi aporte
caseclassPersona(nombre:String,edad:Int) def fiesta(x:Persona)={ x match {case y if y.edad>=18&& y.nombre.toLowerCase()=="maria"=>"Esta Maria si puede entrar"case y if y.edad<=18&& y.nombre.toLowerCase()=="maria"=>"Esta Maria no puede entrar"case_=>"Donde esta Maria?"}} val persona1 =Persona("Maria",20) val persona2 =Persona("maria",14) val persona3 =Persona("Andrea",45)println(fiesta(persona1))println(fiesta(persona2))println(fiesta(persona3))
Listo!!
def m(x:Persona)= x match {case y if y.edad>=18&& y.nombre=="Maria"=>"Hola Maria! Eres mayor de edad"case y if y.edad<18&& y.nombre=="Maria"=>"Hola maria! No eres mayor de edad"case y if y.edad>=18&& y.nombre=="Jose"=>"Hola Jose! Eres mayor de edad"case y if y.edad<18&& y.nombre=="Jose"=>"Hola Jose! No eres mayor de edad"case_=>"¿Quien eres?"}