cv.cm

Pemrograman · Bahasa pemrograman

Tutorial Scala untuk pemula

6 menit baca

Jawaban singkat

Scala adalah bahasa JVM bertipe statis yang memadukan pemrograman berorientasi objek dan fungsional, banyak dipakai untuk data engineering dengan Apache Spark dan untuk backend konkuren. Fitur utamanya adalah type inference, koleksi immutable, case class, dan pattern matching. Halaman ini memakai Scala 3 untuk membahas setup, value, alur kontrol, fungsi, koleksi, trait, enum, dan penanganan error dengan Option, Either, dan Try.

Apa itu Scala dan untuk apa digunakan

Scala adalah bahasa bertipe statis yang memadukan pemrograman berorientasi objek dan fungsional. Scala dibuat oleh Martin Odersky di EPFL dan berjalan terutama di Java Virtual Machine, dengan Scala.js untuk browser dan Scala Native untuk binary native. Kode Scala bisa memakai library Java apa pun.

Scala banyak dipakai untuk data engineering (Apache Spark ditulis dengan Scala), untuk backend konkuren dan terdistribusi (Akka, Pekko, ZIO, Cats Effect), serta untuk sistem keuangan dan streaming. Tutorial ini memakai sintaks Scala 3, yang mengizinkan blok berbasis indentasi; kurung kurawal tetap berfungsi.

Instal Scala dan jalankan Hello, world

Installer yang direkomendasikan adalah Coursier (cs setup), yang menginstal perintah scala dan JDK. Di Scala 3, method yang diberi anotasi @main adalah titik masuk program.

// hello.scala
@main def hello(): Unit =
  println("Hello, world!")
scala run hello.scala
# Hello, world!

Untuk proyek yang lebih besar, sbt dan Mill adalah build tool yang umum. Scastie (scastie.scala-lang.org) menjalankan Scala di browser tanpa instalasi apa pun.

Value, variabel, dan tipe dasar

Gunakan val untuk nilai immutable dan var untuk variabel yang bisa diubah. Tipe ditebak otomatis tetapi bisa ditulis setelah titik dua. Scala yang idiomatis memakai val hampir di mana-mana.

val name = "Scala"            // String
var count: Int = 1            // mutable
count += 1
val ratio = 3.0 / 4           // Double: 0.75
val big = 12345678901L        // Long
val ok = count > 1            // Boolean
println(s"$name: count=$count ratio=$ratio ok=$ok")
// Scala: count=2 ratio=0.75 ok=true
println(f"pi is ${math.Pi}%.3f")   // pi is 3.142
TipeContohCatatan
Int42bilangan bulat bertanda 32-bit
Long42Lbilangan bulat bertanda 64-bit
Double3.14bilangan floating point 64-bit
Booleantruetrue atau false
String"hi"String Java; interpolator s"..." dan f"..."
Unit()seperti void: tidak ada nilai yang bermakna

Semua di Scala adalah ekspresi: if, blok, dan match semuanya mengembalikan nilai, sehingga Anda jarang membutuhkan var sementara.

Alur kontrol dan pattern matching

if mengembalikan nilai. for mengiterasi rentang dan koleksi, dan dengan yield ia membangun koleksi baru. match adalah pattern matching Scala yang andal, fitur khas bahasa ini.

val n = 7
val parity = if n % 2 == 0 then "even" else "odd"
println(parity)                        // odd
for i <- 1 to 3 do print(s"$i ")       // 1 2 3
println()
val squares = for i <- 1 to 4 yield i * i
println(squares)                       // Vector(1, 4, 9, 16)
def describe(x: Any): String = x match
  case 0             => "zero"
  case i: Int if i < 0 => "negative int"
  case i: Int        => s"int $i"
  case s: String     => s"string of length ${s.length}"
  case (a, b)        => s"pair $a and $b"
  case _             => "something else"
println(describe(-5))                  // negative int
println(describe("hey"))               // string of length 3
println(describe((1, "x")))            // pair 1 and x

1 to 3 menyertakan 3; 1 until 3 berhenti sebelum 3. case _ terakhir adalah wildcard yang cocok dengan apa saja; tanpanya, nilai yang tidak cocok akan melempar MatchError.

Fungsi dan higher-order function

Method didefinisikan dengan def. Fungsi adalah nilai: bisa disimpan, dikirim sebagai argumen, dan dikembalikan. Parameter bisa punya nilai default, dan pemanggil bisa memakai named argument.

def add(a: Int, b: Int): Int = a + b
def greet(name: String, greeting: String = "Hello"): String =
  s"$greeting, $name!"
val double = (x: Int) => x * 2        // function value
def applyTwice(f: Int => Int, x: Int): Int = f(f(x))
println(add(2, 3))                    // 5
println(greet("Ann"))                 // Hello, Ann!
println(greet("Ann", greeting = "Hi")) // Hi, Ann!
println(applyTwice(double, 5))        // 20
println(List(1, 2, 3, 4).filter(_ % 2 == 0).map(_ * 10)) // List(20, 40)

Underscore pada _ * 10 adalah singkatan untuk lambda satu parameter, x => x * 10.

Koleksi

Koleksi standar bersifat immutable secara default: operasi seperti map, filter, dan :+ mengembalikan koleksi baru dan membiarkan yang asli tidak berubah. Versi mutable ada di scala.collection.mutable.

val nums = List(5, 3, 8)
val more = nums :+ 1                  // List(5, 3, 8, 1); nums unchanged
println(more.sorted)                  // List(1, 3, 5, 8)
println(nums.sum)                     // 16
val v = Vector("a", "b", "c")         // fast indexed access
println(v(1))                         // b
val ages = Map("Ann" -> 31, "Bo" -> 25)
println(ages("Ann"))                  // 31
println(ages.get("Zed"))              // None
println(ages.getOrElse("Zed", 0))     // 0
val unique = Set(1, 2, 2, 3)
println(unique.size)                  // 3
val words = List("apple", "avocado", "banana")
println(words.groupBy(_.head)('a'))  // List(apple, avocado)
KoleksiGunakan untuk
Listlinked list immutable; prepend dan akses head/tail cepat
Vectorsequence ber-indeks immutable; default umum yang bagus
Mappencarian key-value
Setelemen unik dan pengecekan keanggotaan
Arrayarray Java mutable berukuran tetap

Case class, trait, dan enum

case class adalah tipe data immutable yang otomatis mendapat equality, toString, copy, dan dukungan pattern matching. trait mirip interface yang juga bisa berisi kode. Scala 3 menambahkan enum untuk tipe data aljabar.

trait Shape:
  def area: Double
case class Circle(r: Double) extends Shape:
  def area: Double = math.Pi * r * r
case class Rect(w: Double, h: Double) extends Shape:
  def area: Double = w * h
enum Color:
  case Red, Green, Blue
@main def shapes(): Unit =
  val all: List[Shape] = List(Circle(1), Rect(2, 3))
  all.foreach(s => println(f"$s area=${s.area}%.2f"))
  // Circle(1.0) area=3.14
  // Rect(2.0,3.0) area=6.00
  val r = Rect(2, 3)
  println(r == Rect(2, 3))            // true
  println(r.copy(h = 10))             // Rect(2.0,10.0)
  println(Color.values.toList)        // List(Red, Green, Blue)

Fitur khas lainnya mencakup given dan using (parameter kontekstual, dulu disebut implicit), extension method, opaque type, dan union type seperti Int | String.

Penanganan error dengan Option, Either, dan Try

Scala mendukung try, catch, dan finally, tetapi kode yang idiomatis memodelkan kegagalan dengan tipe. Option bernilai Some(value) atau None; Either berisi error Left atau hasil Right; Try menangkap exception sebagai Failure.

import scala.util.{Try, Success, Failure}
def parseInt(s: String): Option[Int] = s.toIntOption
def safeDivide(a: Int, b: Int): Either[String, Int] =
  if b == 0 then Left("division by zero") else Right(a / b)
println(parseInt("42"))               // Some(42)
println(parseInt("x"))                // None
println(safeDivide(10, 2))            // Right(5)
println(safeDivide(1, 0))             // Left(division by zero)
Try("abc".toInt) match
  case Success(n) => println(s"got $n")
  case Failure(e) => println(s"failed: ${e.getClass.getSimpleName}")
// failed: NumberFormatException

Program lengkap kecil: laporan nilai

Program ini mengurai baris name,score, melewati baris yang tidak valid, dan mencetak rata-rata tiap siswa. Program ini memakai case class, Option, groupBy, dan pemformatan string.

case class Score(name: String, value: Int)
def parse(line: String): Option[Score] =
  line.split(",").map(_.trim) match
    case Array(name, v) => v.toIntOption.map(Score(name, _))
    case _              => None
@main def report(): Unit =
  val lines = List("ann, 90", "bo, 70", "ann, 80", "broken line", "bo, x")
  val scores = lines.flatMap(parse)
  val averages = scores.groupBy(_.name).view.mapValues { list =>
    list.map(_.value).sum.toDouble / list.size
  }.toList.sortBy(_._1)
  for (name, avg) <- averages do
    println(f"$name%-4s $avg%.1f")
// ann  85.0
// bo   70.0

Langkah selanjutnya

  • Scala 3 Book di docs.scala-lang.org, yang membahas bahasa ini dari dasar hingga contextual abstraction.
  • Scala Toolkit untuk tugas sehari-hari seperti file, JSON, dan HTTP.
  • Dokumentasi Apache Spark jika Anda ingin memakai Scala untuk pemrosesan data.
  • Kursus yang ditautkan dari scala-lang.org, termasuk kursus pemrograman fungsional EPFL.

FAQ

Sebaiknya belajar Scala 2 atau Scala 3?

Pelajari Scala 3 untuk proyek baru. Scala 2.13 masih ditemukan di banyak codebase yang ada, termasuk sebagian ekosistem Spark, dan sebagian besar konsep intinya sama.

Apakah Scala bahasa fungsional?

Scala berorientasi objek sekaligus fungsional. Setiap nilai adalah objek, tetapi fungsi adalah nilai kelas satu, koleksi immutable secara default, dan pattern matching menjadi pusatnya.

Apa perbedaan val dan var di Scala?

val mendefinisikan nilai yang tidak bisa diberi nilai ulang, dan var mendefinisikan variabel yang bisa. Scala yang idiomatis lebih memilih val bersama koleksi immutable.

Apa itu case class?

Case class adalah class yang ditujukan untuk data immutable. Compiler menghasilkan structural equality, toString yang mudah dibaca, method copy, dan dukungan pattern matching.

Apakah Scala masih dipakai?

Ya. Scala tetap menjadi bahasa inti untuk Apache Spark, platform streaming dan data, serta library backend fungsional seperti ZIO dan Cats Effect.

Semua tutorial pemrograman