La gestió d'errors és una part fonamental de qualsevol llenguatge de programació, i Scala no és una excepció. En la programació funcional, la gestió d'errors es fa sovint de manera diferent a la programació imperativa tradicional. En aquest tema, explorarem com gestionar errors de manera funcional en Scala utilitzant estructures com Option
, Either
i Try
.
Conceptes Clau
- Immutabilitat: Les estructures de dades immutables són fonamentals en la programació funcional. Això significa que un cop creats, els valors no poden canviar.
- Monads: Les monads són estructures que encapsulen un valor i proporcionen una manera de manipular aquest valor de manera segura i composable.
- Gestió d'Errors: En lloc d'utilitzar excepcions, la programació funcional utilitza estructures de dades com
Option
,Either
iTry
per representar errors de manera explícita.
Option
L'objecte Option
representa un valor que pot o no estar present. Pot ser Some(value)
si el valor està present, o None
si no ho està.
Exemple
def findUserById(id: Int): Option[String] = { val users = Map(1 -> "Alice", 2 -> "Bob") users.get(id) } val user1 = findUserById(1) // Some("Alice") val user2 = findUserById(3) // None
Explicació
findUserById
retorna unOption[String]
.- Si l'usuari existeix, retorna
Some(value)
. - Si l'usuari no existeix, retorna
None
.
Either
L'objecte Either
representa un valor que pot ser de dos tipus: Left
per a errors i Right
per a valors correctes.
Exemple
def divide(a: Int, b: Int): Either[String, Int] = { if (b == 0) Left("Cannot divide by zero") else Right(a / b) } val result1 = divide(4, 2) // Right(2) val result2 = divide(4, 0) // Left("Cannot divide by zero")
Explicació
divide
retorna unEither[String, Int]
.- Si
b
és 0, retornaLeft
amb un missatge d'error. - Si
b
no és 0, retornaRight
amb el resultat de la divisió.
Try
L'objecte Try
s'utilitza per encapsular operacions que poden llançar excepcions. Pot ser Success(value)
si l'operació té èxit, o Failure(exception)
si falla.
Exemple
import scala.util.{Try, Success, Failure} def parseInt(s: String): Try[Int] = Try(s.toInt) val result1 = parseInt("123") // Success(123) val result2 = parseInt("abc") // Failure(java.lang.NumberFormatException)
Explicació
parseInt
retorna unTry[Int]
.- Si la cadena es pot convertir a un enter, retorna
Success
. - Si la cadena no es pot convertir, retorna
Failure
amb l'excepció corresponent.
Exercicis Pràctics
Exercici 1: Utilitzant Option
Escriu una funció que busqui un producte per ID en un mapa de productes. Si el producte no existeix, retorna None
.
def findProductById(id: Int): Option[String] = { val products = Map(1 -> "Laptop", 2 -> "Smartphone") // Implementa la funció aquí }
Solució
def findProductById(id: Int): Option[String] = { val products = Map(1 -> "Laptop", 2 -> "Smartphone") products.get(id) }
Exercici 2: Utilitzant Either
Escriu una funció que calculi la radicació quadrada d'un nombre. Si el nombre és negatiu, retorna un missatge d'error.
Solució
def sqrt(x: Double): Either[String, Double] = { if (x < 0) Left("Cannot calculate square root of a negative number") else Right(Math.sqrt(x)) }
Exercici 3: Utilitzant Try
Escriu una funció que llegeixi un fitxer i retorni el seu contingut com una cadena. Si el fitxer no existeix, retorna una excepció.
import scala.util.{Try, Success, Failure} import scala.io.Source def readFile(filename: String): Try[String] = { // Implementa la funció aquí }
Solució
import scala.util.{Try, Success, Failure} import scala.io.Source def readFile(filename: String): Try[String] = { Try(Source.fromFile(filename).getLines.mkString("\n")) }
Resum
En aquest tema, hem après com gestionar errors de manera funcional en Scala utilitzant Option
, Either
i Try
. Aquestes estructures ens permeten representar errors de manera explícita i composable, evitant l'ús d'excepcions tradicionals. Hem vist exemples pràctics i hem realitzat exercicis per reforçar els conceptes apresos. En el proper tema, explorarem conceptes avançats de Scala, com les conversions i els paràmetres implícits.
Curs de Programació en Scala
Mòdul 1: Introducció a Scala
- Introducció a Scala
- Configuració de l'Entorn de Desenvolupament
- Conceptes Bàsics de Scala: Sintaxi i Estructura
- Variables i Tipus de Dades
- Operacions Bàsiques i Expressions
Mòdul 2: Estructures de Control i Funcions
- Declaracions Condicionals
- Bucles i Iteracions
- Funcions i Mètodes
- Funcions d'Ordre Superior
- Funcions Anònimes
Mòdul 3: Col·leccions i Estructures de Dades
- Introducció a les Col·leccions
- Llistes i Arrays
- Conjunts i Mapes
- Tuples i Options
- Coincidència de Patrons
Mòdul 4: Programació Orientada a Objectes en Scala
- Classes i Objectes
- Herència i Traits
- Classes Abstractes i Classes Case
- Objectes Companys
- Objectes Singleton
Mòdul 5: Programació Funcional en Scala
- Immutabilitat i Funcions Pures
- Estructures de Dades Funcionals
- Monads i Functors
- For-Comprehensions
- Gestió d'Errors en la Programació Funcional
Mòdul 6: Conceptes Avançats de Scala
- Conversions i Paràmetres Implícits
- Classes de Tipus i Polimorfisme
- Macros i Reflexió
- Concurrència en Scala
- Introducció a Akka