Objektorientiert und funktional auf der JVM
Ausführen: Im Browser mit Scastie (scastie.scala-lang.org) oder lokal mit scala-cli run Hallo.scala.
@main def, Einrückungssyntax in Scala 3, val (unveränderlich) vor varif, Blöcke)s"..." und f"..."scala-cli run Hallo.scala
scala-cli test .
scala-cli repl # interaktive Konsole
scalac -d out Hallo.scala && scala -cp out hallo # klassischOption[T] mit Some/None statt nullif/match sind Ausdrücke; for ... yield; Bereiche 1 to 5, untildef, Standardwerte, Int*, Funktionen als Werte, @tailrec@main def main(): Unit =
val i = 42
val d = 3.14
val s = "Text"
val c = 'x'
val b = true
val l = 3_000_000_000L
println(s"${i.getClass.getSimpleName} ${d.getClass.getSimpleName} ${s.getClass.getSimpleName} ${c.getClass.getSimpleName}")
println(s"${7 / 2} ${7 % 3} ${7 / 2.0} ${math.pow(2, 10)} ${math.sqrt(144)} ${math.abs(-5)} ${math.max(3, 9)}")
println(s"${i.toDouble} ${d.toInt} ${i.toString + "!"} ${"123".toInt + 1} ${"2.5".toDouble} ${"x".toIntOption} ${"7".toIntOption}")
println(s"${5.max(3)} ${5.min(3)} ${10.toBinaryString} ${255.toHexString} ${i.isValidInt} ${1 to 5} ${(1 to 5).toList}")
val text = "Hallo Welt"
println(s"${text.length} ${text.toUpperCase} ${text.substring(0, 5)} ${text.contains("Welt")} ${text.indexOf("W")}")
println(s"${text.split(" ").toList} ${text.replace("l", "L")} ${text.reverse} ${text.take(3)} ${text.drop(6)} ${"ab" * 3}")
println(s"${text.charAt(0)} ${text(1)} ${text.startsWith("Hal")} ${" trim ".trim} ${text.toList.take(3)} ${text.count(_ == 'l')}")
println("Mehrzeilig:\n" + """Zeile 1
|Zeile 2 mit "Anführungszeichen"
|""".stripMargin)List, Vector, Set, Map; veränderlich in scala.collection.mutablemap, filter, foldLeft, groupBy, zip, sliding, flatMapmatch mit Mustern: Werte, Typen, case class, Listen, Tupel, Guards (if)val-Definitionen@main def main(): Unit =
val z = List(5, 3, 9, 1, 7)
println(s"${z.head} ${z.tail} ${z.last} ${z.length} ${z(2)} ${z.take(2)} ${z.drop(3)}")
println(s"${0 :: z} ${z :+ 100} ${z ++ List(8)} ${z.reverse} ${z.sorted} ${z.sortBy(-_)} ${z.sortWith(_ > _)}")
println(s"${z.map(_ * 2)} ${z.filter(_ > 4)} ${z.sum} ${z.product} ${z.min} ${z.max} ${z.size}")
println(s"${z.exists(_ > 8)} ${z.forall(_ > 0)} ${z.count(_ % 2 == 1)} ${z.find(_ > 5)} ${z.indexOf(9)} ${z.contains(3)}")
println(s"${z.foldLeft(0)(_ + _)} ${z.reduce(_ max _)} ${z.partition(_ > 4)} ${z.zip("abcde")} ${z.sliding(2).toList}")
println(s"${z.grouped(2).toList} ${z.takeWhile(_ > 2)} ${z.dropWhile(_ > 2)} ${z.span(_ > 2)} ${z.splitAt(2)}")
println(s"${List(List(1, 2), List(3)).flatten} ${List("ab", "cd").flatMap(_.toList)} ${z.distinct} ${z.mkString(", ")} ${z.mkString("[", ";", "]")}")
println(s"${List(1, 2, 2, 3, 3, 3).groupBy(identity).view.mapValues(_.size).toMap.toList.sorted}")
println(s"${List("a", "bb", "ccc").map(_.length)} ${(1 to 5).toList.scanLeft(0)(_ + _)} ${List.fill(3)("x")} ${List.range(0, 10, 3)} ${List.tabulate(4)(i => i * i)}")
println(s"${z.zipWithIndex} ${z.lift(10)} ${z.lift(1)} ${z.collect { case x if x > 4 => x * 10 }} ${z.maxBy(x => (x - 5).abs)}")class mit Primärkonstruktor in der Klassenkopfzeile; val/var macht Parameter zu Feldernobject = Singleton, Companion Object für statische Teilecase class liefert Gleichheit, copy, toString und Pattern Matchingtrait = Schnittstelle + Verhalten, mehrere Traits mischbarclass Konto(val inhaber: String, private var stand: Double = 0.0):
def einzahlen(betrag: Double): Unit =
require(betrag > 0, "Betrag muss positiv sein")
stand += betrag
def kontostand: Double = stand
override def toString: String = f"Konto($inhaber, $stand%.2f)"
object Zaehler:
private var n = 0
def naechster(): Int =
n += 1
n
@main def main(): Unit =
val k = Konto("Mia", 10)
k.einzahlen(5.5)
println(k)
println(k.kontostand)
println(Zaehler.naechster())
println(Zaehler.naechster())
try k.einzahlen(-1)
catch case e: IllegalArgumentException => println(e.getMessage)enum für Aufzählungen und ADTs, sealed für Exhaustivitäts-PrüfungOption für Fehlendes, Either für Fehler mit Grund, Try kapselt Ausnahmenfor-Comprehensions verketten diese Typentry/catch/finally bleiben für Ausnahmefälleenum Farbe:
case Rot, Gruen, Blau
enum Form:
case Kreis(r: Double)
case Rechteck(b: Double, h: Double)
def flaeche(f: Form): Double = f match
case Form.Kreis(r) => math.Pi * r * r
case Form.Rechteck(b, h) => b * h
@main def main(): Unit =
println(Farbe.Rot)
println(Farbe.values.toList)
println(Farbe.valueOf("Blau").ordinal)
println(Farbe.Gruen == Farbe.Gruen)
println(f"${flaeche(Form.Kreis(1))}%.2f")
println(flaeche(Form.Rechteck(2, 3)))[A], Kontextparameter mit using und Instanzen mit givengiven-Instanzenextension fügt Methoden zu bestehenden Typen hinzuopaque type und Union Types (A | B) sind neu in Scala 3def 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")))Future mit for, Await nur in Tests oder mainlazy val, LazyList und view verzögern BerechnungenUsing schließt Ressourcen sichersbt, scala-cli, mill; Editor: Metalsimport scala.concurrent.{Future, Await}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.*
def quadrat(n: Int): Future[Int] = Future { n * n }
@main def main(): Unit =
val f = for
a <- quadrat(3)
b <- quadrat(4)
yield a + b
println(Await.result(f, 5.seconds))
val viele = Future.sequence((1 to 5).map(quadrat))
println(Await.result(viele, 5.seconds))
val fehler = Future { 1 / 0 }.recover { case _: ArithmeticException => -1 }
println(Await.result(fehler, 5.seconds))@main def main(): Unit =
val l = List(3, 1, 2)
val tabelle = List(
"map" -> l.map(_ + 1),
"filter" -> l.filter(_ > 1),
"sorted" -> l.sorted,
"foldLeft" -> l.foldLeft(0)(_ + _),
"zip" -> l.zip(List("a", "b", "c")),
"groupBy" -> l.groupBy(_ % 2).toList.sortBy(_._1),
"flatMap" -> l.flatMap(x => List(x, x)),
"take/drop" -> (l.take(2), l.drop(2)),
)
tabelle.foreach((n, w) => println(s"$n: $w"))