0Pricing
Scala for Backend Engineering & Functional Programming · Aula

Compondo Either

map e flatMap.

Compondo Either é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.

Compondo cálculos

Programas reais encadeiam várias etapas sujeitas a falhas: analisar, validar, consultar e calcular. Either permite compô-las de modo que a primeira falha interrompa toda a cadeia.

As ferramentas são map, flatMap e as compreensões for.

flatMap encadeia Eithers

flatMap aplica uma função que também retorna um Either. Se o receptor for um Left, a função nunca será chamada e o Left continuará se propagando.

object Main {
  def positive(n: Int): Either[String, Int] =
    if (n > 0) Right(n) else Left("not positive")

  def main(args: Array[String]): Unit = {
    val r = Right(5).flatMap(positive)
    val l = Right(-1).flatMap(positive)
    println(r)
    println(l)
  }
}

Interrupção antecipada

Quando você encadeia várias chamadas de flatMap, o primeiro Left interrompe tudo. As etapas seguintes são ignoradas, e esse erro se torna o resultado final.

object Main {
  def step(label: String, n: Int): Either[String, Int] = {
    println(s"running $label")
    Right(n + 1)
  }

  def main(args: Array[String]): Unit = {
    val result = Left("early error").asInstanceOf[Either[String, Int]]
      .flatMap(n => step("A", n))
      .flatMap(n => step("B", n))
    println(result)
  }
}

Compreensão for sobre Either

Como Either é orientado à direita, você pode usá-lo em uma compreensão for. Cada <- extrai um Right; qualquer Left interrompe a compreensão e se torna o resultado.

object Main {
  def parse(s: String): Either[String, Int] =
    s.toIntOption.toRight(s"bad: $s")

  def main(args: Array[String]): Unit = {
    val sum = for {
      a <- parse("3")
      b <- parse("4")
    } yield a + b
    println(sum)
  }
}

Uma compreensão for com falha

Se qualquer etapa da compreensão produzir um Left, toda a expressão será esse Left, e as etapas seguintes não serão executadas.

object Main {
  def parse(s: String): Either[String, Int] =
    s.toIntOption.toRight(s"bad: $s")

  def main(args: Array[String]): Unit = {
    val sum = for {
      a <- parse("3")
      b <- parse("oops")
      c <- parse("5")
    } yield a + b + c
    println(sum)
  }
}

Encadeando validações

Um fluxo realista: analise uma string, verifique uma regra de negócio e depois transforme o resultado. Cada etapa retorna um Either.

object Main {
  def parse(s: String): Either[String, Int] = s.toIntOption.toRight("not a number")
  def checkRange(n: Int): Either[String, Int] =
    if (n >= 1 && n <= 100) Right(n) else Left("out of range")

  def process(s: String): Either[String, Int] =
    parse(s).flatMap(checkRange).map(_ * 10)

  def main(args: Array[String]): Unit = {
    println(process("7"))
    println(process("500"))
    println(process("x"))
  }
}

map versus flatMap

Use map quando sua função retornar um valor simples. Use flatMap quando ela retornar outro Either, para evitar um Either[String, Either[String, Int]] aninhado.

@main def run(): Unit = {
  val withMap: Either[String, Int] = Right(2).map(_ + 1)
  val nested: Either[String, Either[String, Int]] = Right(2).map(n => Right(n + 1))
  val flat: Either[String, Int] = Right(2).flatMap(n => Right(n + 1))
  println(withMap)
  println(nested)
  println(flat)
}

Combinando valores independentes

Uma compreensão for também funciona quando cada etapa não depende da anterior. Todas precisam ter sucesso para que o yield final seja executado.

object Main {
  def parse(s: String): Either[String, Int] = s.toIntOption.toRight(s"bad: $s")

  def main(args: Array[String]): Unit = {
    val combined = for {
      x <- parse("10")
      y <- parse("20")
      z <- parse("30")
    } yield List(x, y, z).sum
    println(combined)
  }
}

Transformação de erros no estilo leftMap

A biblioteca padrão Either não possui leftMap, mas você pode transformar o erro com swap.map(...).swap ou mapeando dentro de um fold. Isso mantém os tipos de erro consistentes em todo o fluxo.

@main def run(): Unit = {
  val e: Either[String, Int] = Left("low-level error")
  val mapped = e.swap.map(msg => s"context: $msg").swap
  println(mapped)
}

Reunindo tudo

Um pequeno fluxo de calculadora que analisa dois números e faz uma divisão, informando qualquer falha como um erro tipado.

object Main {
  def parse(s: String): Either[String, Int] = s.toIntOption.toRight(s"bad number: $s")
  def divide(a: Int, b: Int): Either[String, Int] =
    if (b == 0) Left("division by zero") else Right(a / b)

  def calc(x: String, y: String): Either[String, Int] =
    for {
      a <- parse(x)
      b <- parse(y)
      r <- divide(a, b)
    } yield r

  def main(args: Array[String]): Unit = {
    println(calc("20", "4"))
    println(calc("20", "0"))
    println(calc("x", "4"))
  }
}

Por que isso é importante

Compor Either proporciona uma programação orientada a ferrovias: o caminho normal passa por Right, e qualquer erro é desviado para a trilha Left, ignorando o restante. Sem exceções, sem verificações de nulo, apenas valores.

Verificação rápida

Teste sua compreensão sobre a composição de Either.

Recapitulação

Você aprendeu a compor Either:

  • flatMap encadeia etapas sujeitas a falhas e interrompe a cadeia no primeiro Left.
  • As compreensões for tornam claros os fluxos com várias etapas.
  • Use map para resultados simples e flatMap para funções que retornam Either.
  • Transforme erros com swap.map(...).swap.

Perguntas Frequentes

A aula “Compondo Either” é grátis?

Sim — o texto completo de “Compondo Either” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.

O que vou aprender em “Compondo Either”?

map e flatMap. Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?

Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Compondo Either”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?

Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Either para erros
  2. Try, Success, Failure
  3. Compondo Either
  4. Convertendo entre tipos
← Voltar para Scala for Backend Engineering & Functional Programming