0Pricing
Scala for Backend Engineering & Functional Programming · Pelajaran

Pola Akumulator

Bawa keadaan selama rekursi.

Pola Akumulator adalah pelajaran Scala for Backend Engineering & Functional Programming gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Scala for Backend Engineering & Functional Programming, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Scala for Backend Engineering & Functional Programming mencakup 4 pelajaran total.

Mengapa Menggunakan Akumulator

Rekursi biasa membangun hasil saat kembali naik melalui tumpukan pemanggilan, setelah pemanggilan rekursif selesai.

Akumulator justru membawa hasil sementara turun ke setiap pemanggilan, sehingga jawaban sudah siap saat kasus dasar tercapai.

Perubahan kecil ini memungkinkan rekursi ekor dan penggunaan tumpukan yang konstan.

Fungsi Pembantu

Pola akumulator menggunakan pembantu internal yang menerima parameter tambahan: hasil sementara.

Fungsi luar cukup memulainya dengan nilai awal, biasanya 0 atau list kosong.

def sum(xs: List[Int]): Int = {
  def loop(rest: List[Int], acc: Int): Int = rest match {
    case Nil    => acc
    case h :: t => loop(t, acc + h)
  }
  loop(xs, 0)
}

Menjalankan Akumulator

Di sini, program lengkap menjumlahkan list menggunakan akumulator.

Perhatikan bahwa kasus dasar mengembalikan acc secara langsung, bukan 0. Totalnya telah dibangun saat kita menelusuri list ke bawah.

def sum(xs: List[Int]): Int = {
  def loop(rest: List[Int], acc: Int): Int = rest match {
    case Nil    => acc
    case h :: t => loop(t, acc + h)
  }
  loop(xs, 0)
}

@main def run(): Unit =
  println(sum(List(1, 2, 3, 4)))  // 10

Membandingkan Dua Bentuk

Dalam rekursi biasa, langkah penggabungan (h + ...) menunggu pemanggilan di dalamnya selesai.

Dalam versi akumulator, penggabungan terjadi sebelum pemanggilan, dan pemanggilan tersebut menjadi hal terakhir yang dilakukan fungsi.

Sifat sebagai pemanggilan terakhir inilah yang membuatnya menjadi rekursi ekor.

// Plain: combine after the call
case h :: t => h + sum(t)

// Accumulator: combine before the call
case h :: t => loop(t, acc + h)

Rekursi Ekor

Pemanggilan rekursi ekor adalah pemanggilan ketika pemanggilan rekursif menjadi tindakan terakhir fungsi, tanpa pekerjaan tersisa setelahnya.

Scala dapat mengoptimalkannya menjadi perulangan dengan menggunakan kembali satu bingkai tumpukan, sehingga tumpukan tidak pernah meluap sedalam apa pun rekursinya.

import scala.annotation.tailrec

@tailrec
def countDown(n: Int): Unit =
  if (n < 0) ()
  else { println(n); countDown(n - 1) }

Anotasi @tailrec

Menambahkan @tailrec meminta kompiler memverifikasi bahwa fungsi tersebut benar-benar merupakan rekursi ekor.

Jika tidak, kompilasi gagal dengan kesalahan yang jelas. Ini mengubah jebakan kinerja yang tidak terlihat menjadi jaminan saat pembangunan.

import scala.annotation.tailrec

def sum(xs: List[Int]): Int = {
  @tailrec
  def loop(rest: List[Int], acc: Int): Int = rest match {
    case Nil    => acc
    case h :: t => loop(t, acc + h)
  }
  loop(xs, 0)
}

@main def run(): Unit = println(sum((1 to 100000).toList))

Mengakumulasikan List

Akumulator tidak harus menyimpan angka. Akumulator juga dapat membangun koleksi.

Fungsi reverse ini menambahkan setiap kepala ke bagian depan akumulator, yang secara alami membalik urutan. Penambahan ke bagian depan dengan :: berlangsung cepat, sehingga cara ini efisien.

def reverse[A](xs: List[A]): List[A] = {
  def loop(rest: List[A], acc: List[A]): List[A] = rest match {
    case Nil    => acc
    case h :: t => loop(t, h :: acc)
  }
  loop(xs, Nil)
}

Reverse dalam Praktik

Akumulator dimulai dalam keadaan kosong dan bertambah saat kita menggunakan input.

Karena setiap kepala didorong ke bagian depan acc, elemen pertama akhirnya berada di posisi terakhir, sehingga menghasilkan list terbalik dengan biaya tumpukan konstan.

def reverse[A](xs: List[A]): List[A] = {
  def loop(rest: List[A], acc: List[A]): List[A] = rest match {
    case Nil    => acc
    case h :: t => loop(t, h :: acc)
  }
  loop(xs, Nil)
}

@main def run(): Unit =
  println(reverse(List(1, 2, 3)))  // List(3, 2, 1)

Beberapa Akumulator

Sebuah pembantu dapat membawa beberapa akumulator sekaligus.

Di sini, kita melacak hasil kali sementara dan jumlah elemen dalam perulangan yang sama, lalu mengembalikan keduanya sebagai tuple.

Masing-masing meneruskan nilainya yang telah diperbarui ke pemanggilan berikutnya.

def stats(xs: List[Int]): (Int, Int) = {
  def loop(rest: List[Int], prod: Int, count: Int): (Int, Int) =
    rest match {
      case Nil    => (prod, count)
      case h :: t => loop(t, prod * h, count + 1)
    }
  loop(xs, 1, 0)
}

Memilih Nilai Awal

Akumulator awal harus menjadi elemen identitas untuk operasi Anda.

Untuk penjumlahan gunakan 0, untuk perkalian gunakan 1, untuk membangun list gunakan Nil, dan untuk menggabungkan string gunakan string kosong.

Nilai awal yang salah dapat secara diam-diam menghasilkan jawaban yang salah.

// addition  -> seed 0
// product   -> seed 1
// list      -> seed Nil
// string    -> seed ""

Urutan Hasil

Rekursi dengan akumulator memproses elemen dari kiri ke kanan, tetapi akumulator yang menambahkan ke bagian depan akan membalikkannya.

Jika Anda perlu mempertahankan urutan saat membangun list, balik list di akhir atau tambahkan ke bagian belakang, meskipun penambahan ke bagian belakang lebih lambat. Menambahkan ke depan lalu membalik adalah cara yang umum.

def mapInc(xs: List[Int]): List[Int] = {
  def loop(rest: List[Int], acc: List[Int]): List[Int] = rest match {
    case Nil    => acc.reverse
    case h :: t => loop(t, (h + 1) :: acc)
  }
  loop(xs, Nil)
}

Pemeriksaan Singkat

Pilih pernyataan yang tepat tentang rekursi dengan akumulator.

Ringkasan

Akumulator meneruskan hasil sementara melalui pemanggilan rekursif, sehingga kasus dasar dapat mengembalikannya secara langsung.

Hal ini menempatkan pemanggilan rekursif pada posisi ekor, sehingga mengaktifkan pengoptimalan pemanggilan ekor Scala dan pemeriksaan keamanan @tailrec.

Awali akumulator dengan nilai identitas operasi, lalu balik hasil di akhir jika urutan penting.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Pola Akumulator” gratis?

Ya — teks lengkap “Pola Akumulator” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Scala for Backend Engineering & Functional Programming, upgrade ke CoddyKit PRO. Kursus Scala for Backend Engineering & Functional Programming mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Pola Akumulator”?

Bawa keadaan selama rekursi. Kamu berlatih Scala for Backend Engineering & Functional Programming dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Scala for Backend Engineering & Functional Programming?

Tidak diperlukan pengalaman sebelumnya. Scala for Backend Engineering & Functional Programming di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Pola Akumulator” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Scala for Backend Engineering & Functional Programming ini?

Ya. Setiap pelajaran Scala for Backend Engineering & Functional Programming menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Berpikir Secara Rekursif
  2. Pola Akumulator
  3. foldLeft dan foldRight
  4. reduce dan aggregate
← Kembali ke Scala for Backend Engineering & Functional Programming