0Pricing
Scala for Backend Engineering & Functional Programming · Lekcja

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 map i flatMap
  • Option przerywa działanie po None
  • Either i Try przerywają działanie po niepowodzeniu, zachowując informacje o błędzie
  • Future sekwencjonuje 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

  1. Desugaring for
  2. Filtrowanie za pomocą if
  3. Wiele generatorów
  4. Używanie Option i Future
← Powrót do Scala for Backend Engineering & Functional Programming