Kurz: class Kiste[A](val inhalt: A): def map[B](f: A => B): Kiste[B] = Kiste(f(inhalt)) override def toString = s”Kiste($inhalt)”
Teil des Kurses Scala
Generics
def zweimal[A](x: A): List[A] = List(x, x)
class Kiste[A](val inhalt: A):
def map[B](f: A => B): Kiste[B] = Kiste(f(inhalt))
override def toString = s"Kiste($inhalt)"
def groesster[A](l: List[A])(using ord: Ordering[A]): A = l.reduce((a, b) => if ord.gt(a, b) then a else b)
@main def main(): Unit =
println(zweimal("hi"))
println(Kiste(21).map(_ * 2))
println(groesster(List(3, 8, 5)))
println(groesster(List("b", "z", "a")))Ausgabe:
List(hi, hi)
Kiste(42)
8
zFunktionen höherer Ordnung und Currying
def addiere(a: Int)(b: Int): Int = a + b
val plus5 = addiere(5)
val verkette = (f: Int => Int, g: Int => Int) => f.andThen(g)
@main def main(): Unit =
println(plus5(10))
println(addiere(1)(2))
val f = verkette(_ + 1, _ * 10)
println(f(4))
val teilweise: Int => Int = math.max(3, _)
println(List(1, 5, 2).map(teilweise))
val zaehler = { var n = 0; () => { n += 1; n } }
println((zaehler(), zaehler(), zaehler()))Ausgabe:
15
3
50
List(3, 5, 3)
(1,2,3)Given und Using (Typklassen)
Typklassen erlauben neues Verhalten für bestehende Typen:
trait Beschreibbar[A]:
def beschreibe(a: A): String
given Beschreibbar[Int] with
def beschreibe(a: Int) = s"Zahl $a"
given Beschreibbar[String] with
def beschreibe(a: String) = s"Text '$a'"
given [A](using b: Beschreibbar[A]): Beschreibbar[List[A]] with
def beschreibe(l: List[A]) = l.map(b.beschreibe).mkString("[", ", ", "]")
def zeige[A](a: A)(using b: Beschreibbar[A]): String = b.beschreibe(a)
@main def main(): Unit =
println(zeige(5))
println(zeige("hi"))
println(zeige(List(1, 2)))Ausgabe:
Zahl 5
Text 'hi'
[Zahl 1, Zahl 2]Extension Methods
extension (s: String)
def istPalindrom: Boolean = s == s.reverse
def wiederhole(n: Int): String = s * n
extension [A](l: List[A])
def zweites: Option[A] = l.lift(1)
@main def main(): Unit =
println("anna".istPalindrom)
println("ab".wiederhole(3))
println(List(1, 2, 3).zweites)
println(List(1).zweites)Ausgabe:
true
ababab
Some(2)
NoneOpaque Types und Union Types
object Typen:
opaque type Meter = Double
object Meter:
def apply(d: Double): Meter = d
extension (m: Meter)
def wert: Double = m
def +(o: Meter): Meter = m + o
def zeige(x: Int | String): String = x match
case i: Int => s"Int $i"
case s: String => s"String $s"
@main def main(): Unit =
import Typen.*
println((Meter(1.5) + Meter(2)).wert)
println(zeige(3))
println(zeige("a"))Ausgabe:
3.5
Int 3
String aMerke
- Generics
[A], Kontextparameter mitusingund Instanzen mitgiven - Typklassen = Trait +
given-Instanzen extensionfügt Methoden zu bestehenden Typen hinzuopaque typeund Union Types (A | B) sind neu in Scala 3
Übungsaufgabe
Schreibe eine Typklasse Ordnung[A] mit Instanzen für Int und String.
Quiz zur Selbstkontrolle
Wofür dient using?
- Für implizit übergebene Kontextparameter (richtig)
- Zum Importieren
- Für Schleifen
- Für Klassen
Was definiert given?
- Eine Instanz, die automatisch gefunden wird (richtig)
- Einen Import
- Eine Variable ohne Wert
- Einen Fehler
Was sind extension methods?
- Methoden, die bestehenden Typen nachträglich hinzugefügt werden (richtig)
- Datei-Erweiterungen
- Netzwerkbefehle
- Tests
Weiter im Kurs
Zurück: Enums, ADTs und Fehlerbehandlung
Weiter: Nebenläufigkeit und Ökosystem
Alle Kapitel: Scala im Überblick