Belajar Scala - Sintaks Dasar: Val, Var & Fungsi
Episode 4 of 23

Belajar Scala - Sintaks Dasar: Val, Var & Fungsi

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.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

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.

Val vs Var: Immutable vs Mutable

Scala menyediakan dua keyword untuk mengikat nama ke nilai:

val dan var
val pi = 3.14       // immutable - tidak bisa di-reassign
var counter = 0     // mutable - bisa diubah
counter += 1        // ok
pi = 3.14159        // error: reassignment to val
  • val — 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):

Hindari var - gunakan nilai baru
// 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).sum

Keduanya 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.

Type Inference

Scala bisa menyimpulkan tipe dari nilai, sehingga kalian tidak wajib menuliskannya:

Inference bekerja otomatis
val name = "Sari"       // String
val age = 25            // Int
val ratio = 0.75        // Double
val active = true       // Boolean

Tipe tetap ada dan ketat — inference hanya menyembunyikan penulisan, bukan melonggarkan aturan. Jika kalian lebih suka eksplisit, tulis tipenya:

Anotasi tipe eksplisit
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 dengan def

Fungsi dideklarasikan dengan def. Bentuk dasarnya:

Anatomi def
def namaFungsi(param1: Tipe1, param2: Tipe2): TipeHasil = body

Contoh nyata:

Fungsi dasar
def greet(name: String): String = s"Hello, $name!"
 
def areaCircle(r: Double): Double = Math.PI * r * r

Pemanggilan sama seperti bahasa lain: greet("Budi").

Single-Expression Body

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:

Body multi-baris tanpa return
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.

Parameter Tanpa Kurung vs Dengan Kurung

Scala mengizinkan definisi tanpa kurung — mirip property:

Tanpa kurung untuk accessor ringan
def upper = name.toUpperCase

Aturan praktis komunitas: tanpa kurung jika fungsi tidak punya efek samping dan murah dihitung (aksesor); dengan kurung jika ada efek samping atau perhitungan berat.

Default Arguments dan Named Arguments

Default Arguments

Parameter bisa punya nilai bawaan, sehingga pemanggil bisa melewatkannya:

Default arguments
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 3

Named Arguments

Pemanggilan bisa menyebut nama parameter — sangat membantu untuk fungsi dengan banyak argumen:

Named arguments meningkatkan keterbacaan
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.

Fungsi Sebagai Nilai (Higher-Order Preview)

Di Scala, fungsi bisa disimpan dalam variabel dan dioper ke fungsi lain — inilah fondasi gaya functional:

Fungsi sebagai nilai
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.

Common Pitfalls

  • 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.
  • Tipe hasil fungsi tidak dianotasi untuk API publik — inference untuk lokal itu ok, untuk API itu kontrak yang harus jelas.
  • Mutasi argumen — Scala mendorong fungsi yang tidak mengubah argumennya, melainkan mengembalikan nilai baru.

Penutup

Inti yang harus dibawa pulang:

  • val immutable adalah default; var hanya untuk kasus yang benar-benar butuh mutasi.
  • Type inference menyingkat penulisan tanpa melonggarkan ketegasan tipe.
  • Fungsi def memakai single-expression body tanpa return.
  • Default dan named arguments membuat API lebih fleksibel dan kode pemanggilan lebih terbaca.
  • Fungsi bisa diperlakukan sebagai nilai — pintu masuk ke gaya functional.

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!

Belajar Scala - Sintaks Dasar: Val, Var & Fungsi | Belajar Scala