Usando Option e Future
Encadeamento monádico.
Usando Option e Future é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 4 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.
Além das coleções
As compreensões for não se limitam a listas. Qualquer tipo que forneça map e flatMap pode ser usado, incluindo Option, Either, Try e Future. Isso é chamado de encadeamento monádico.
object Main {
def main(args: Array[String]): Unit = {
val sum = for {
a <- Some(10)
b <- Some(20)
} yield a + b
println(sum)
}
}Option interrompe ao encontrar None
Com Option, a compreensão produz um resultado somente se todos os geradores forem Some. Se algum for None, o resultado inteiro será None e as etapas posteriores serão ignoradas.
object Main {
def main(args: Array[String]): Unit = {
val ok = for {
a <- Some(2)
b <- Some(3)
} yield a * b
val missing = for {
a <- Some(2)
b <- None: Option[Int]
} yield a * b
println(ok)
println(missing)
}
}Encadeando consultas opcionais
Um padrão comum: consultar chaves em um Map, em que cada consulta retorna um Option. A compreensão for produz um valor somente se todas as consultas forem bem-sucedidas.
object Main {
def main(args: Array[String]): Unit = {
val prices = Map("apple" -> 3, "bread" -> 5)
val total = for {
a <- prices.get("apple")
b <- prices.get("bread")
} yield a + b
println(total)
val missing = for {
a <- prices.get("apple")
c <- prices.get("milk")
} yield a + c
println(missing)
}
}Por que isso é melhor do que if-else aninhado
Sem compreensões for, você teria de aninhar correspondências de padrões ou verificações de nulos. A forma monádica transforma essa pirâmide em uma sequência linear e limpa.
object Main {
def parse(s: String): Option[Int] = s.toIntOption
def main(args: Array[String]): Unit = {
val result = for {
x <- parse("40")
y <- parse("2")
} yield x + y
println(result)
}
}As guardas também funcionam com Option
Uma guarda dentro de uma compreensão de Option transforma um valor em None quando a condição falha, atuando como uma validação embutida.
object Main {
def main(args: Array[String]): Unit = {
def validate(age: Int): Option[Int] =
for {
a <- Some(age)
if a >= 18
} yield a
println(validate(25))
println(validate(15))
}
}Apresentando Future
Um Future representa um valor que estará disponível mais tarde. Assim como Option, ele possui map e flatMap, portanto as compreensões for encadeiam etapas assíncronas.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
object Main {
def main(args: Array[String]): Unit = {
val f = for {
a <- Future(10)
b <- Future(20)
} yield a + b
println(Await.result(f, 2.seconds))
}
}Os Future são executados sequencialmente aqui
Quando um gerador depende de outro dentro de uma compreensão for, os Future são executados em sequência, porque cada flatMap espera o resultado anterior.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
object Main {
def main(args: Array[String]): Unit = {
val f = for {
a <- Future(5)
b <- Future(a * 2)
} yield a + b
println(Await.result(f, 2.seconds))
}
}Executando Future em paralelo
Para executar Future em paralelo, inicie-os antes da compreensão for e depois combine-os. O trabalho independente se sobrepõe, em vez de esperar.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
object Main {
def main(args: Array[String]): Unit = {
val fa = Future(100)
val fb = Future(200)
val combined = for {
a <- fa
b <- fb
} yield a + b
println(Await.result(combined, 2.seconds))
}
}Either para erros mais detalhados
Either[E, A] carrega um valor de erro quando ocorre uma falha. Em uma compreensão for, o primeiro Left interrompe a execução e é retornado.
object Main {
def parse(s: String): Either[String, Int] =
s.toIntOption.toRight(s"not a number: $s")
def main(args: Array[String]): Unit = {
val good = for { a <- parse("3"); b <- parse("4") } yield a + b
val bad = for { a <- parse("3"); b <- parse("x") } yield a + b
println(good)
println(bad)
}
}A mesma estrutura, muitos tipos
Observe que a compreensão parece idêntica ao usar Option, Either, Try ou Future. Somente a semântica de falha muda. Essa uniformidade é o poder do encadeamento monádico.
import scala.util.Try
object Main {
def main(args: Array[String]): Unit = {
val result = for {
a <- Try("21".toInt)
b <- Try("2".toInt)
} yield a * b
println(result)
}
}Não é permitido misturar tipos
Todos os geradores de uma compreensão devem pertencer à mesma mônada. Você não pode misturar diretamente um gerador de Option com um gerador de Future; primeiro converta um deles (por exemplo, usando Future.fromTry ou envolvendo o Option).
object Main {
def main(args: Array[String]): Unit = {
// Convert the Option to keep types consistent
val maybe: Option[Int] = Some(7)
val result = for {
a <- maybe
b <- maybe.map(_ + 1)
} yield a + b
println(result)
}
}Verificação rápida
Em uma compreensão for de Option, o que acontece se um gerador produzir None?
Recapitulação
Você aprendeu o encadeamento monádico com compreensões for:
- Funciona com qualquer tipo que tenha
mapeflatMap Optioninterrompe ao encontrarNoneEithereTryinterrompem em caso de falha, carregando informações sobre o erroFutureencadeia etapas assíncronas; inicie-as cedo para obter paralelismo- Todos os geradores devem compartilhar o mesmo tipo de mônada
Perguntas Frequentes
A aula “Usando Option e Future” é grátis?
Sim — o texto completo de “Usando Option e Future” é 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 “Usando Option e Future”?
Encadeamento monádico. 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 4 de 4.
Quanto tempo leva a aula “Usando Option e Future”?
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
- Dessugar de for
- Filtrando com if
- Vários geradores
- Usando Option e Future