Komponowanie Either
map i flatMap
Komponowanie Either to bezpłatna lekcja Scala for Backend Engineering & Functional Programming na CoddyKit. To lekcja 3 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.
Komponowanie obliczeń
Rzeczywiste programy łączą kilka etapów, które mogą zakończyć się niepowodzeniem: parsowanie, walidację, wyszukiwanie i obliczenia. Either pozwala komponować takie etapy, tak aby pierwsze niepowodzenie natychmiast kończyło cały łańcuch.
Służą do tego map, flatMap oraz konstrukcje for.
flatMap łączy wartości Either
flatMap stosuje funkcję, która sama zwraca Either. Jeśli odbiorcą jest Left, funkcja nie zostaje wywołana, a Left jest propagowane dalej.
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)
}
}Przerywanie przy błędzie
Gdy łączą Państwo wiele wywołań flatMap, pierwsze Left zatrzymuje całe przetwarzanie. Późniejsze etapy są pomijane, a ten błąd staje się wynikiem końcowym.
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)
}
}Konstrukcja for dla Either
Ponieważ Either działa prawostronnie, można używać go w konstrukcji for. Każdy operator <- rozpakowuje wartość Right; dowolny Left zatrzymuje konstrukcję i staje się jej wynikiem.
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)
}
}Nieudana konstrukcja for
Jeśli dowolny etap konstrukcji zwróci Left, całe wyrażenie przyjmuje tę wartość Left, a kolejne etapy nie są wykonywane.
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)
}
}Łączenie walidacji
Realistyczny potok: sparsowanie ciągu znaków, sprawdzenie reguły biznesowej, a następnie przekształcenie. Każdy etap zwraca 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 a flatMap
Należy użyć map, gdy funkcja zwraca zwykłą wartość. flatMap stosuje się, gdy zwraca kolejny obiekt Either, aby uniknąć zagnieżdżenia Either[String, Either[String, Int]].
@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)
}Łączenie niezależnych wartości
Konstrukcja for działa również wtedy, gdy poszczególne etapy nie zależą od poprzedniego. Wszystkie muszą zakończyć się sukcesem, aby wykonała się końcowa instrukcja yield.
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)
}
}Transformacja błędów w stylu leftMap
Standardowa biblioteka nie udostępnia dla Either metody leftMap, ale błąd można przekształcić za pomocą swap.map(...).swap lub przez mapowanie wewnątrz fold. Pozwala to zachować spójne typy błędów w całym potoku.
@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)
}Połączenie wszystkiego
Niewielki potok kalkulatora, który parsuje dwie liczby i wykonuje dzielenie, zgłaszając każde niepowodzenie jako typowany błąd.
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"))
}
}Dlaczego to ma znaczenie
Komponowanie Either daje programowanie zorientowane na tory: ścieżka sukcesu przebiega przez Right, a każdy błąd zbacza na tor Left i omija pozostałą część. Bez wyjątków, bez sprawdzania wartości null, tylko wartości.
Szybkie sprawdzenie
Sprawdźmy, czy rozumieją Państwo komponowanie Either.
Podsumowanie
Opanował(a) Pan/Pani komponowanie Either:
flatMapłączy etapy, które mogą zakończyć się niepowodzeniem, i przerywa działanie przy pierwszymLeft.- Konstrukcje
forułatwiają czytelny zapis wieloetapowych potoków. - Należy używać
mapdla zwykłych wyników, aflatMapdla funkcji zwracających Either. - Błędy można przekształcać za pomocą
swap.map(...).swap.
Ucz się Scala dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 39
- Lekcje
- 143
Często zadawane pytania
Czy lekcja „Komponowanie Either” jest bezpłatna?
Tak — pełny tekst „Komponowanie Either” 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 „Komponowanie Either”?
map i flatMap Ć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 3 z 4.
Ile czasu zajmuje lekcja „Komponowanie Either”?
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
- Either do obsługi błędów
- Try, Success, Failure
- Komponowanie Either
- Konwersja między typami