21. Fungsi

Kamu sudah memanggil fungsi sejak Bab 7 — print, io.read, tonumber, math.random, string.format. Sekarang saatnya kamu menulis fungsimu sendiri: sebuah fungsi memberi nama pada sekumpulan pekerjaan yang bisa kamu gunakan berulang kali.

Mendefinisikan dan memanggil

Definisi paling sederhana:

local function greet()
    print("Hello!")
end

greet()   -- mencetak Hello!
greet()   -- mencetak Hello! lagi

Baca seperti ini: definisikan fungsi lokal greet yang tidak menerima argumen dan menjalankan isinya saat dipanggil. end menutup isi fungsi; panggil dengan menuliskan namanya diikuti ().

local adalah keyword yang sama yang kamu pakai untuk variabel: ia membuat fungsi bersifat privat di dalam file. Tanpa local, fungsi menjadi global — seperti biasa, pakai local.

Parameter

Sebuah fungsi menerima masukan sebagai parameter di dalam tanda kurung:

local function greet(name)
    print("Hello, " .. name .. "!")
end

greet("Keiko")    -- Hello, Keiko!
greet("Roblox")   -- Hello, Roblox!

name hanya ada selama satu kali pemanggilan; pemanggilnya menyediakan nilainya (disebut argumen) berdasarkan posisi. Kalau lebih dari satu:

local function add(a, b)
    print(a .. " + " .. b .. " = " .. (a + b))
end

add(3, 4)   -- 3 + 4 = 7

Argumen yang tidak diberikan akan menjadi nil; argumen berlebih diabaikan tanpa error.

greet()           -- name bernilai nil; mencoba menggabungkan nil dan akan error
add(1, 2, 3, 4)   -- berjalan, 3 dan 4 diabaikan

return — mengembalikan nilai

Untuk menghasilkan sebuah nilai alih-alih mencetak, gunakan return:

local function square(n)
    return n * n
end

local result = square(5)
print(result)              -- 25
print(square(7))           -- 49
print(square(3) + 1)       -- 10

return langsung mengakhiri fungsi dan mengembalikan nilainya. Fungsi tanpa return mengembalikan nil.

Buka exercises/21/01-square.lua. Tambahkan fungsi cube(n) yang mengembalikan n * n * n, lalu panggil cube(3).

Beberapa nilai kembalian

Fungsi Lua bisa mengembalikan beberapa nilai sekaligus:

local function divmod(a, b)
    return a // b, a % b
end

local q, r = divmod(17, 5)
print(q, r)   -- 3  2

Ini salah satu fitur Lua yang paling keren. Fitur ini akan muncul lagi di bab 22 bersama table.unpack, dan kamu sudah melihatnya di bab 11 sebagai a, b = b, a — trik tukar nilai dari sisi yang berbeda.

Ketika hanya satu nilai yang diharapkan (di dalam .., atau sebagai argumen), hanya nilai pertama yang dipakai; sisanya dibuang.

return dini untuk pengecekan awal

Karena return langsung mengakhiri fungsi, ia berguna untuk menangani kasus mudah lebih dulu:

local function absolute(n)
    if n >= 0 then
        return n
    end
    return -n
end

print(absolute(5))    -- 5
print(absolute(-7))   -- 7

Tidak perlu else: jika cabang pertama cocok, fungsi langsung keluar di sana dan baris setelah if tidak pernah dijalankan. Ini disebut guard, atau early return.

Scope: di mana variabel hidup

Sebuah variabel local hidup di dalam blok tempat ia dideklarasikan — untuk fungsi, itu adalah isi fungsinya. Begitu fungsi selesai, variabel lokal itu hilang:

local function counter_step()
    local count = 0
    count = count + 1
    return count
end

print(counter_step())   -- 1
print(counter_step())   -- 1   (bukan 2)
print(counter_step())   -- 1

Setiap pemanggilan mendapat count yang baru. Untuk menyimpan nilai antar pemanggilan, deklarasikan variabel itu di luar fungsi:

local count = 0

local function step()
    count = count + 1
    return count
end

print(step())   -- 1
print(step())   -- 2
print(step())   -- 3

Ini berjalan karena fungsi di dalam bisa melihat dan mengubah count yang ada di atasnya. Kamu akan sering menggunakan pola ini.

PR

Soal 1 — Greet

Buka exercises/21/homework/01-greet.lua. Tulis sebuah local function greet(name) yang mencetak Hello, <name>!. Panggil dengan tiga nama yang berbeda.

Soal 2 — is_even

Buka exercises/21/homework/02-is-even.lua. Tulis is_even(n) yang mengembalikan (bukan mencetak) true atau false bergantung apakah n adalah bilangan genap. Panggil dengan beberapa nilai di dalam print agar boolean-nya terlihat.

Soal 3 — Clamp

Buka exercises/21/homework/03-clamp.lua. Tulis clamp(x, lo, hi) yang mengembalikan lo jika x kurang dari lo, mengembalikan hi jika lebih dari hi, dan mengembalikan x jika di antaranya. Uji dengan tiga pemanggilan yang mencakup masing-masing kasus.

Tantangan — Swap

Buka exercises/21/homework/04-swap.lua. Tulis swap(a, b) yang mengembalikan dua nilai dengan posisi tertukar. Lalu deklarasikan dua variabel, panggil swap pada keduanya, tangkap hasilnya kembali ke nama yang sama, dan cetak sebelum dan sesudah — menggunakan nilai kembalian ganda dan penugasan ganda dari bab 11.

Buntu atau sudah selesai? Buka halaman solusi PR.