Menguasai dua cara mendeklarasikan nilai di Scala — val immutable yang dianjurkan dan var mutable yang dibatasi — beserta type inference dan fungsi: parameter bertipe, default arguments, named arguments, hingga single-expression body yang menjadi ciri khas gaya functional Scala.

Setelah di episode 3 kalian berhasil menjalankan program pertama, sekarang kita masuk ke jantung sintaks Scala: bagaimana nilai dideklarasikan dan bagaimana fungsi dibentuk. Dua hal ini — val vs var dan def — adalah batu bata semua program Scala, dan memahami keduanya dengan benar akan menentukan kualitas kode kalian berbulan-bulan ke depan.
Mengapa episode ini penting? Karena salah satu perbedaan terbesar antara developer yang "menulis Java dengan sintaks Scala" dan developer yang benar-benar Scala adalah pemahaman mereka tentang immutability sebagai default. Kalian tidak sedang mempelajari keyword baru; kalian sedang melatih cara berpikir.
Scala menyediakan dua keyword untuk mengikat nama ke nilai:
val pi = 3.14 // immutable - tidak bisa di-reassign
var counter = 0 // mutable - bisa diubah
counter += 1 // ok
pi = 3.14159 // error: reassignment to valval — mengikat nama ke nilai sekali, untuk selamanya. Nilainya tidak bisa diubah setelah binding. Ini default yang dianjurkan.var — mengikat nama ke nilai yang bisa diganti kapan saja.Keyakinan komunitas Scala: mulai dengan val, dan gunakan var hanya jika benar-benar dibutuhkan (dan bahkan itu biasanya bisa dihindari dengan pendekatan fungsional):
// gaya imperatif dengan var
var sum = 0
for (x <- List(1, 2, 3)) sum += x
// gaya fungsional dengan val
val sum = List(1, 2, 3).sumKeduanya menghasilkan 6, tetapi versi kedua lebih aman: tidak ada state yang bisa "bocor" atau diubah dari tempat lain. Sebuah val memberi jaminan kepada siapa pun yang membaca kode: nilai ini tidak akan berubah.
Note
"Immutability is default" bukan berarti "var adalah dosa". Ada kasus nyata (accumulator di loop ketat, cache performa) di mana var wajar. Polanya: val adalah default, var adalah keputusan sadar dengan alasan.
Scala bisa menyimpulkan tipe dari nilai, sehingga kalian tidak wajib menuliskannya:
val name = "Sari" // String
val age = 25 // Int
val ratio = 0.75 // Double
val active = true // BooleanTipe tetap ada dan ketat — inference hanya menyembunyikan penulisan, bukan melonggarkan aturan. Jika kalian lebih suka eksplisit, tulis tipenya:
val name: String = "Sari"
def greet(person: String): String = s"Hello, $person"Untuk API publik (method di library atau class), anotasi eksplisit dianjurkan agar pembaca langsung tahu kontraknya; untuk val lokal, inference sudah cukup.
Fungsi dideklarasikan dengan def. Bentuk dasarnya:
def namaFungsi(param1: Tipe1, param2: Tipe2): TipeHasil = bodyContoh nyata:
def greet(name: String): String = s"Hello, $name!"
def areaCircle(r: Double): Double = Math.PI * r * rPemanggilan sama seperti bahasa lain: greet("Budi").
Ciri khas Scala: jika body fungsi hanya satu ekspresi, ia tidak butuh kurung kurawal — cukup = ekspresi. Jika kalian memiliki beberapa pernyataan, baris terakhir adalah hasilnya:
def describe(n: Int): String =
val doubled = n * 2
s"angka $n dikali dua = $doubled"Perhatikan tidak ada keyword return. Ekspresi terakhir secara otomatis menjadi nilai yang dikembalikan. Ini bukan sekadar gaya — ini menghilangkan satu kelas bug (return di tengah alur yang membingungkan) dan membuat fungsi terdorong untuk menjadi murni.
Scala mengizinkan definisi tanpa kurung — mirip property:
def upper = name.toUpperCaseAturan praktis komunitas: tanpa kurung jika fungsi tidak punya efek samping dan murah dihitung (aksesor); dengan kurung jika ada efek samping atau perhitungan berat.
Parameter bisa punya nilai bawaan, sehingga pemanggil bisa melewatkannya:
def connect(host: String, port: Int = 8080, retries: Int = 3): String =
s"connect ke $host:$port, retry $retries kali"
connect("localhost") // port 8080, retries 3
connect("localhost", port = 9090) // retries tetap 3Pemanggilan bisa menyebut nama parameter — sangat membantu untuk fungsi dengan banyak argumen:
connect(host = "api.example.com", retries = 5, port = 443)Urutan tidak perlu sama dengan definisi. Ini membuat kode pemanggilan jauh lebih jelas: pembaca langsung tahu retries = 5 berarti jumlah percobaan ulang, tanpa perlu menghafal posisi parameter.
Di Scala, fungsi bisa disimpan dalam variabel dan dioper ke fungsi lain — inilah fondasi gaya functional:
val double: Int => Int = x => x * 2
val result = List(1, 2, 3).map(double)Int => Int dibaca "dari Int ke Int" — tipe fungsi yang menerima satu Int dan mengembalikan Int. map menerima fungsi seperti ini dan menerapkannya ke setiap elemen. Ini sekadar pengantar; map/filter/flatMap akan kita bedah penuh di episode 6.
return yang tidak perlu — di Scala, return adalah jejak gaya imperatif; gunakan ekspresi terakhir.var di mana val cukup — lawan kebiasaan dari bahasa lain; kode akan lebih mudah diuji.Inti yang harus dibawa pulang:
val immutable adalah default; var hanya untuk kasus yang benar-benar butuh mutasi.def memakai single-expression body tanpa return.Di episode 5 selanjutnya, kita membedah tipe data dan type system — Int, Long, Double, Boolean, String, Char, Unit, dan tipe-tipe yang membedakan Scala dari bahasa lain: Option, Either, dan Tuple, plus case class, enum, given/using, dan opaque type. Sampai jumpa di episode 5!