Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin · Oppitunti

for-lausekkeen purkaminen

map ja flatMap.

Oppitunti 1/413 vaihetta

for-lausekkeen purkaminen on ilmainen Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin-kurssilla on yhteensä 4 oppituntia.

Mikä on for-comprehension?

Scalan for-comprehension on erityinen syntaksi kokoelmien ja muiden säilötyyppien käsittelyyn. Se näyttää imperatiiviselta silmukalta, mutta on todellisuudessa syntaktinen lyhenne, jonka kääntäjä muuttaa map-, flatMap-, filter- ja foreach-kutsuiksi.

Syntaksin purkamisen ymmärtäminen auttaa päättelemään minkä tahansa for-comprehension-rakenteen toiminnan, myös mukautettujen tyyppien yhteydessä.

object Main {
  def main(args: Array[String]): Unit = {
    val result = for (x <- List(1, 2, 3)) yield x * 10
    println(result)
  }
}

Yksi generaattori muuttuu map-metodiksi

Kun for-comprehension sisältää täsmälleen yhden generaattorin ja käyttää yield-avainsanaa, kääntäjä muuttaa sen yhdeksi map-kutsuksi.

  • for (x <- xs) yield f(x)
  • muuttuu muotoon xs.map(x => f(x))
object Main {
  def main(args: Array[String]): Unit = {
    val a = for (x <- List(1, 2, 3)) yield x + 1
    val b = List(1, 2, 3).map(x => x + 1)
    println(a == b)
  }
}

yield-avainsana

yield-avainsana käskee Scalaa kokoamaan tulokset uuden, samantyyppisen kokoelman sisään.

Ilman yield-avainsanaa for-comprehension suorittaa sivuvaikutuksen jokaiselle alkiolle ja palauttaa Unit-arvon (se muuttuu foreach-kutsuksi).

object Main {
  def main(args: Array[String]): Unit = {
    // No yield: side effect only
    for (x <- List("a", "b")) println(x)
    // With yield: builds a new List
    val upper = for (x <- List("a", "b")) yield x.toUpperCase
    println(upper)
  }
}

Kaksi generaattoria muuttuu flatMap- ja map-kutsuiksi

Kun generaattoreita on vähintään kaksi, ulommat muuttuvat flatMap-kutsuiksi ja sisin map-kutsuksi.

  • for (x <- xs; y <- ys) yield f(x, y)
  • muuttuu muotoon xs.flatMap(x => ys.map(y => f(x, y)))
object Main {
  def main(args: Array[String]): Unit = {
    val pairs = for {
      x <- List(1, 2)
      y <- List("a", "b")
    } yield (x, y)
    println(pairs)
  }
}

Vastaavan flatMap-kutsun tarkastelu

Tässä kirjoitamme saman logiikan molemmilla tavoilla. Niiden samanarvoisuuden osoittaminen vahvistaa, että for-comprehension ei lisää taikuutta vaan ainoastaan luettavuutta.

object Main {
  def main(args: Array[String]): Unit = {
    val sugar = for {
      x <- List(1, 2)
      y <- List(10, 20)
    } yield x + y

    val desugared = List(1, 2).flatMap(x => List(10, 20).map(y => x + y))

    println(sugar)
    println(sugar == desugared)
  }
}

Miksi ulommalle generaattorille käytetään flatMap-metodia

Jokainen ulompi alkio tuottaa kokonaisen kokoelman sisempiä tuloksia. Jos ulommalle generaattorille käytettäisiin map-metodia, tuloksena olisi sisäkkäinen kokoelma, kuten List(List(...), List(...)).

flatMap litistää sisäkkäiset listat yhdeksi litteäksi tulokseksi.

object Main {
  def main(args: Array[String]): Unit = {
    val nested = List(1, 2).map(x => List(10, 20).map(y => x + y))
    val flat   = List(1, 2).flatMap(x => List(10, 20).map(y => x + y))
    println(nested)
    println(flat)
  }
}

yield-oton for muuttuu foreach-kutsuksi

For-silmukka, jossa ei ole yield-avainsanaa, muutetaan foreach-kutsuksi. Se suorittaa rungon sivuvaikutukset ja tuottaa Unit-arvon.

  • for (x <- xs) doSomething(x)
  • muuttuu muotoon xs.foreach(x => doSomething(x))
object Main {
  def main(args: Array[String]): Unit = {
    val r: Unit = for (x <- List(1, 2, 3)) print(x + " ")
    println()
    println("Return type is Unit")
  }
}

Tulostyyppi määräytyy ensimmäisen generaattorin mukaan

Tuloksen tyyppi määräytyy ensimmäisen generaattorin kokoelman mukaan. List-kokoelman päällä oleva for tuottaa List-arvon, Set-kokoelman päällä oleva Set-arvon ja Option-arvon päällä oleva Option-arvon.

object Main {
  def main(args: Array[String]): Unit = {
    val fromList = for (x <- List(1, 2, 2, 3)) yield x
    val fromSet  = for (x <- Set(1, 2, 2, 3)) yield x
    println(fromList)
    println(fromSet)
  }
}

Arvojen sitominen merkillä =

For-comprehensionin sisällä voitte sitoa väliaikaisia arvoja merkillä =. Tämä välttää uudelleenlaskentaa ja parantaa luettavuutta.

Se puretaan map-kutsuksi, joka kuljettaa ylimääräisen arvon mukana tuplessa.

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- List(1, 2, 3)
      doubled = x * 2
    } yield doubled + 1
    println(result)
  }
}

Toimii kaikilla map- ja flatMap-metodit sisältävillä tyypeillä

Koska syntaksin purkaminen perustuu vain map- ja flatMap-metodeihin, for-comprehension toimii kaikilla tyypeillä, jotka määrittelevät nämä metodit: Option, Either, Try, Future ja omat luokkanne.

object Main {
  def main(args: Array[String]): Unit = {
    val combined = for {
      a <- Some(2)
      b <- Some(3)
    } yield a * b
    println(combined)
  }
}

Todellinen hyöty on luettavuus

Verratkaa syvästi sisäkkäistä flatMap/map-ketjua selkeään for-comprehension-rakenteeseen. Ne käännetään samaksi koodiksi, mutta for-versio etenee ylhäältä alas reseptin tavoin.

object Main {
  def main(args: Array[String]): Unit = {
    val chained = List(1, 2).flatMap(a => List(3, 4).map(b => a * b))
    val readable = for {
      a <- List(1, 2)
      b <- List(3, 4)
    } yield a * b
    println(chained == readable)
  }
}

Pikatarkistus

Miten kääntäjä purkaa for-comprehension-rakenteen, jossa on kaksi generaattoria ja yield-avainsana?

Kertaus

Opitte, miten for-comprehension-rakenteet puretaan:

  • Yksi generaattori + yield → map
  • Useita generaattoreita + yield → flatMap (ulompi) + map (sisin)
  • Ei yield-avainsanaa → foreach, joka palauttaa Unit-arvon
  • val =-sidonnat lisäävät väliaikaisia arvoja
  • Tulostyyppi määräytyy ensimmäisen generaattorin mukaan

For-comprehensionissa voidaan käyttää mitä tahansa tyyppiä, jolla on map- ja flatMap-metodit.

Aloita maksutta

Opi Scala tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
39
Oppitunnit
143

Usein kysytyt kysymykset

Onko oppitunti ”for-lausekkeen purkaminen” ilmainen?

Kyllä – oppitunnin ”for-lausekkeen purkaminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin-kurssin, päivitä CoddyKit PROhon. Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”for-lausekkeen purkaminen”?

map ja flatMap. Harjoittelet Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.

Kuinka kauan ”for-lausekkeen purkaminen”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin-oppitunnilla?

Kyllä. Jokainen Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. for-lausekkeen purkaminen
  2. Suodatus if-lausekkeella
  3. Useat generaattorit
  4. Optionin ja Futuren käyttö
← Takaisin: Scala backend-kehitykseen ja funktionaaliseen ohjelmointiin