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

  1. Immutabilitat: Les estructures de dades immutables són fonamentals en la programació funcional. Això significa que un cop creats, els valors no poden canviar.
  2. Monads: Les monads són estructures que encapsulen un valor i proporcionen una manera de manipular aquest valor de manera segura i composable.
  3. Gestió d'Errors: En lloc d'utilitzar excepcions, la programació funcional utilitza estructures de dades com Option, Either i Try 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 un Option[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 un Either[String, Int].
  • Si b és 0, retorna Left amb un missatge d'error.
  • Si b no és 0, retorna Right 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 un Try[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.

def sqrt(x: Double): Either[String, Double] = {
  // Implementa la funció aquí
}

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.

© Copyright 2024. Tots els drets reservats