Fungsi

Definisi fungsi, nilai balik ganda, varargs, dan fungsi sebagai nilai kelas satu.

Daftar isi

Topik ini membahas fungsi Lua secara utuh, mulai dari definisi dan pemanggilan, nilai balik ganda, penanganan argumen berjumlah tidak tetap, kedudukan fungsi sebagai nilai kelas satu, hingga fungsi lokal beserta rekursinya. Setelah menyelesaikannya, fungsi dapat dirancang dengan antarmuka keluaran yang sesuai bagi pemanggilnya.

Definisi dan pemanggilan#

Fungsi didefinisikan dengan kata function, daftar parameter di dalam tanda kurung, badan pernyataan, dan penutup end. Pemanggilan dilakukan dengan menulis nama fungsi diikuti tanda kurung yang memuat argumen, dan tanda kurung itu wajib ada. Definisi diawali local function apabila fungsi hanya digunakan di dalam cakupannya, dan pola ini menjadi pilihan bawaan untuk fungsi pembantu.

lua Contoh: definisi dan pemanggilan fungsi sapa
-- Definisi dan pemanggilan fungsi dengan tanda kurung
local function sapa(nama)
  return "Halo, " .. nama
end
print(sapa("Budi"))
text Keluaran
Halo, Budi

Lua mengizinkan satu pengecualian pada aturan tanda kurung. Apabila pemanggilan menyertakan tepat satu argumen berupa string literal atau konstruktor table, tanda kurung boleh digantikan oleh argumennya langsung, sehingga sapa"Budi" setara dengan sapa("Budi") dan total{ pensil = 24 } setara dengan total({ pensil = 24 }).

lua Contoh: pemanggilan satu argumen string tanpa tanda kurung
-- Satu argumen string boleh dipanggil tanpa tanda kurung
local function sapa(nama)
  return "Halo, " .. nama
end
print(sapa"Budi")
text Keluaran
Halo, Budi
lua Contoh: pemanggilan satu argumen table tanpa tanda kurung
-- Satu argumen berupa konstruktor table juga boleh tanpa tanda kurung
local function total(item)
  local jumlah = 0
  for _, harga in pairs(item) do
    jumlah = jumlah + harga
  end
  return jumlah
end
print(total{ pensil = 24, buku = 10 })
text Keluaran
34

Bentuk tanpa tanda kurung ini banyak muncul pada pustaka Lua untuk konfigurasi singkat, tetapi bentuknya kurang lazim bagi pembaca baru.

Nilai balik ganda#

Pernyataan return boleh mengembalikan lebih dari satu nilai sekaligus, dipisahkan tanda koma. Kemampuan ini menghilangkan kebutuhan membungkus beberapa hasil ke dalam table untuk kasus sederhana, misalnya nilai terkecil dan terbesar dari satu deret skor. Pemanggil menampung hasilnya dengan variabel sebanyak nilai baliknya, dan variabel penampung pun dipisahkan tanda koma.

lua rentang.lua
-- Fungsi mengembalikan nilai terkecil dan terbesar sekaligus
local function rentang(daftar)
  local terkecil = daftar[1]
  local terbesar = daftar[1]
  for _, isi in ipairs(daftar) do
    if isi < terkecil then
      terkecil = isi
    end
    if isi > terbesar then
      terbesar = isi
    end
  end
  return terkecil, terbesar
end

local terkecil, terbesar = rentang({78, 92, 65, 88})
print(terkecil, terbesar)
text Keluaran
65	92

Jumlah nilai balik disesuaikan dengan tempatnya. Penampungan ke beberapa variabel menerima seluruh nilai, penampungan ke satu variabel memangkasnya menjadi satu, dan kekurangan nilai dilengkapi dengan nil.

lua Contoh: penyesuaian jumlah nilai balik pada penampung
-- Jumlah nilai balik disesuaikan dengan jumlah variabel penampung
local function duaNilai()
  return 10, 20
end
local pertama, kedua = duaNilai()
print(pertama, kedua)
local hanyaSatu = duaNilai()
print(hanyaSatu)
text Keluaran
10	20
10

Aturan penyesuaian yang sama berlaku di dalam daftar ekspresi. Pemanggilan fungsi yang berada di tengah daftar dipangkas menjadi satu nilai, sedangkan pemanggilan pada posisi terakhir menyumbang seluruh nilainya. Penulisan tanda kurung di sekeliling pemanggilan, yaitu (duaNilai()), memaksanya menjadi satu nilai pula.

lua Contoh: pemangkasan nilai balik di tengah daftar ekspresi
-- Di tengah daftar ekspresi, nilai balik ganda dipangkas menjadi satu
local function duaNilai()
  return 10, 20
end
print(duaNilai(), "tambahan")
print("tambahan", duaNilai())
text Keluaran
10	tambahan
tambahan	10	20

Vararg#

Ekspresi ... yang disebut vararg menampung seluruh argumen tambahan yang diteruskan pemanggil, dengan jumlah yang tidak tetap. Fungsi yang mendeklarasikan ... di akhir daftar parameternya dapat menerima tiga argumen pada satu pemanggilan dan dua argumen pada pemanggilan lain. Vararg diperlakukan sebagai ekspresi multi-nilai, sehingga dapat dibungkus ke dalam table untuk ditelusuri.

lua Contoh: penjumlahan argumen berjumlah tidak tetap
-- Vararg menampung sejumlah argumen yang tidak tetap
local function jumlahkan(...)
  local total = 0
  for _, isi in ipairs({...}) do
    total = total + isi
  end
  return total
end
print(jumlahkan(10, 20, 30))
print(jumlahkan(5, 5))
text Keluaran
60
10

Pustaka dasar menyediakan fungsi select untuk menangani vararg tanpa membungkusnya. Bentuk select("#", ...) mengembalikan jumlah argumen, sedangkan select(n, ...) mengembalikan argumen mulai posisi ke-n hingga akhir.

lua Contoh: menghitung dan mengambil vararg dengan select
-- select("#", ...) menghitung jumlah argumen, select(n, ...) mengambil sisanya
local function laporkan(...)
  print(select("#", ...))
  print(select(2, ...))
end
laporkan("Ali", "Budi", "Citra")
text Keluaran
3
Budi	Citra

Pasangan table.pack dan table.unpack menyelesaikan kebutuhan sebaliknya. table.pack membungkus argumen menjadi satu table yang menyimpan jumlah aslinya pada kunci n, sedangkan table.unpack menyebar isi table menjadi deretan argumen.

lua Contoh: membungkus dan menyebar argumen dengan table.pack
-- table.pack membungkus vararg, sedangkan table.unpack menyebar table menjadi argumen
local kemasan = table.pack("Ali", "Budi", "Citra")
print(kemasan.n)
print(table.unpack(kemasan))
text Keluaran
3
Ali	Budi	Citra

Fungsi sebagai nilai kelas satu#

Fungsi di Lua merupakan nilai kelas satu (first-class value), yaitu nilai yang dapat ditampung dalam variabel, disimpan sebagai elemen table, diteruskan sebagai argumen, dan dikembalikan sebagai nilai balik. Definisi fungsi sesungguhnya berupa penugasan, sehingga local function sapa tidak berbeda prinsip dengan menampung nilai lain ke variabel lokal.

lua Contoh: fungsi ditampung lewat variabel lain
-- Fungsi dapat ditampung dan dipanggil lewat variabel lain
local function kuadrat(x)
  return x * x
end
local f = kuadrat
print(f(7))
text Keluaran
49

Kedudukan kelas satu ini membuka pola fungsi yang menerima fungsi lain sebagai argumen. Fungsi anonim (anonymous function) dibuat tanpa nama dan ditulis langsung di tempat argumennya, sehingga perilaku kecil tidak perlu diberi nama formal.

lua Contoh: fungsi anonim sebagai argumen
-- Fungsi anonim diteruskan sebagai argumen ke fungsi lain
local function terapkan(daftar, operasi)
  local hasil = {}
  for i, isi in ipairs(daftar) do
    hasil[i] = operasi(isi)
  end
  return hasil
end

local berlipat = terapkan({2, 4, 6}, function(isi) return isi * 3 end)
print(table.unpack(berlipat))
text Keluaran
6	12	18

Fungsi anonim function(isi) return isi * 3 end digunakan sekali oleh terapkan dan tidak meninggalkan nama baru di cakupan luarnya. Pola ini menjadi dasar banyak pustaka Lua, misalnya table.sort yang menerima fungsi pembanding dari pemanggilnya.

Fungsi lokal dan rekursi#

Bentuk local function menetapkan nama fungsi sebagai variabel lokal, dan nama itu langsung terlihat di dalam badannya sendiri. Ciri ini membuat rekursi sederhana dapat ditulis tanpa persiapan tambahan, sebab pemanggilan dirinya sendiri menemukan nama lokal yang sudah dideklarasikan.

lua Contoh: rekursi dengan local function
-- local function membuat nama fungsi terlihat di dalam badannya sendiri
local function hitungMundur(n)
  if n == 0 then
    return
  end
  print(n)
  hitungMundur(n - 1)
end
hitungMundur(3)
text Keluaran
3
2
1

Perilaku itu berbeda dengan penugasan local f = function ... end. Pada bentuk penugasan tersebut, nama f baru berlaku setelah pernyataannya selesai, sehingga badan fungsi tidak melihat nama lokal f dan pemanggilan rekursifnya mencari variabel global dengan nama sama. Kasus serupa menimpa fungsi lokal yang saling memanggil, yaitu ketika satu fungsi memanggil fungsi lokal lain yang belum dideklarasikan.

Solusinya berupa deklarasi maju (forward declaration), yaitu mendeklarasikan nama lokal lebih dahulu, kemudian menugaskan fungsi kepadanya. Dengan nama yang sudah berlaku, badan fungsi dapat memanggil dirinya sendiri maupun fungsi rekannya.

lua Contoh: deklarasi maju untuk rekursi lokal
-- Deklarasi maju memungkinkan fungsi lokal memanggil dirinya sendiri
local faktorial

function faktorial(n)
  if n <= 1 then
    return 1
  end
  return n * faktorial(n - 1)
end

print(faktorial(5))
text Keluaran
120

Ringkasan#

  • Definisi fungsi menggunakan function dengan tanda kurung wajib pada pemanggilan, kecuali argumennya tepat satu berupa string literal atau konstruktor table.
  • return dapat mengembalikan beberapa nilai sekaligus, dan jumlahnya disesuaikan dengan posisi pemanggilan, dipangkas menjadi satu apabila berada di tengah daftar ekspresi.
  • Ekspresi vararg ... menampung argumen berjumlah tidak tetap, ditopang select serta pasangan table.pack dan table.unpack.
  • Fungsi adalah nilai kelas satu yang dapat ditampung, diteruskan, dan dikembalikan, sedangkan rekursi lokal memerlukan local function atau deklarasi maju.

Referensi#

  • Referensi Manual Lua 5.4 — Lua.org — Bagian Function Calls dan Function Definitions menetapkan aturan pemanggilan, penyesuaian nilai balik, dan vararg, sedangkan bagian Basic Functions merinci select serta table.pack dan table.unpack.
  • Programming in Lua — Lua.org — Bab fungsi membahas definisi, nilai balik ganda, fungsi bersarang, dan rekursi beserta idiom deklarasi majunya.