Używanie Option i Future
Łączenie monadyczne
Używanie Option i Future to bezpłatna lekcja Scala for Backend Engineering & Functional Programming na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Scala for Backend Engineering & Functional Programming, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Scala for Backend Engineering & Functional Programming zawiera 4 lekcji w sumie.
Poza kolekcjami
For-comprehensions nie ograniczają się do list. Można używać dowolnego typu udostępniającego map i flatMap, w tym Option, Either, Try i Future. Nazywa się to łańcuchowaniem monadycznym.
object Main {
def main(args: Array[String]): Unit = {
val sum = for {
a <- Some(10)
b <- Some(20)
} yield a + b
println(sum)
}
}Option przerywa działanie po None
W przypadku Option comprehension tworzy wynik tylko wtedy, gdy każdy generator ma wartość Some. Jeśli którykolwiek ma wartość None, cały wynik to None, a późniejsze kroki są pomijane.
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)
}
}Łączenie opcjonalnych wyszukiwań
Częsty wzorzec polega na wyszukiwaniu kluczy w Map, gdzie każde wyszukiwanie zwraca Option. For-comprehension zwraca wartość tylko wtedy, gdy wszystkie wyszukiwania zakończą się powodzeniem.
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)
}
}Dlaczego to lepsze od zagnieżdżonego if-else
Bez for-comprehensions trzeba by zagnieżdżać dopasowania wzorców lub sprawdzenia wartości null. Forma monadyczna spłaszcza tę piramidę do przejrzystej sekwencji liniowej.
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)
}
}Strażniki działają również z Option
Strażnik wewnątrz comprehension dla Option zamienia wartość na None, gdy warunek nie jest spełniony, działając jak walidacja w miejscu.
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))
}
}Wprowadzenie do Future
Future reprezentuje wartość, która będzie dostępna później. Podobnie jak Option udostępnia map i flatMap, więc for-comprehensions pozwalają sekwencjonować kroki asynchroniczne.
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))
}
}Future działają tutaj sekwencyjnie
Gdy jeden generator zależy od drugiego w for-comprehension, obiekty Future działają sekwencyjnie, ponieważ każde flatMap czeka na wynik poprzedniego.
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))
}
}Równoległe uruchamianie obiektów Future
Aby uruchomić obiekty Future równolegle, rozpocznij je przed for-comprehension, a następnie połącz. Niezależne zadania wykonują się nakładająco, zamiast czekać na siebie.
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 dla bogatszych błędów
Either[E, A] przechowuje wartość błędu w razie niepowodzenia. W for-comprehension pierwsza wartość Left przerywa działanie i zostaje zwrócona.
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)
}
}Ten sam kształt, wiele typów
Zauważ, że comprehension wygląda identycznie, niezależnie od tego, czy używasz Option, Either, Try czy Future. Różnią się tylko zasady obsługi niepowodzeń. Ta jednolitość jest siłą łańcuchowania monadycznego.
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)
}
}Mieszanie typów jest niedozwolone
Wszystkie generatory w jednej comprehension muszą należeć do tej samej monady. Nie można bezpośrednio łączyć generatora Option z generatorem Future; najpierw trzeba przekonwertować jeden z nich, na przykład za pomocą Future.fromTry, albo opakować wartość 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)
}
}Szybkie sprawdzenie
Co dzieje się w for-comprehension dla Option, gdy jeden z generatorów zwraca None?
Podsumowanie
Poznałeś(-aś) łańcuchowanie monadyczne za pomocą for-comprehensions:
- Działa z każdym typem udostępniającym
mapiflatMap Optionprzerywa działanie poNoneEitheriTryprzerywają działanie po niepowodzeniu, zachowując informacje o błędzieFuturesekwencjonuje kroki asynchroniczne; uruchom je wcześniej, aby uzyskać równoległość- Wszystkie generatory muszą używać tego samego typu monady
Często zadawane pytania
Czy lekcja „Używanie Option i Future” jest bezpłatna?
Tak — pełny tekst „Używanie Option i Future” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Scala for Backend Engineering & Functional Programming, przejdź na CoddyKit PRO. Kurs Scala for Backend Engineering & Functional Programming zawiera 4 lekcji w sumie.
Co nauczysz się w „Używanie Option i Future”?
Łączenie monadyczne Ćwiczysz Scala for Backend Engineering & Functional Programming z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Scala for Backend Engineering & Functional Programming?
Nie wymagamy żadnego doświadczenia. Scala for Backend Engineering & Functional Programming w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Używanie Option i Future”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Scala for Backend Engineering & Functional Programming?
Tak. Każda lekcja Scala for Backend Engineering & Functional Programming zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Desugaring for
- Filtrowanie za pomocą if
- Wiele generatorów
- Używanie Option i Future