Topik ini membahas tempat hidup sebuah nama di dalam Lua, yaitu perbedaan variabel global dan variabel lokal, aturan cakupan blok, penutupan nama (shadowing) antarcakupan, serta alasan mengurangi penggunaan variabel global. Setelah menyelesaikannya, keputusan menempatkan kata local pada setiap penugasan dapat diambil secara sadar.
Variabel global sebagai perilaku bawaan#
Setiap penugasan yang ditulis tanpa kata local menghasilkan variabel global, di mana pun penugasan itu berada, termasuk di dalam badan fungsi dan blok bersarang. Variabel global tidak perlu dideklarasikan sebelum digunakan, karena penugasan pertamanya sekaligus menjadi pembuatannya. Lua menyimpan seluruh variabel global di dalam sebuah table khusus, dan mekanisme table tersebut dibahas pada bagian lain jalur ini.
Berkas berikut menambah nilai variabel global dari dalam fungsi. Kata local tidak tertulis pada baris penambahannya, sehingga setiap pemanggilan menyentuh variabel global yang sama.
-- Penugasan tanpa local membuat variabel global, bahkan di dalam fungsi
function catat()
jumlah = jumlah + 1
end
jumlah = 0
catat()
catat()
print(jumlah)2Keluaran 2 memperlihatkan bahwa kedua pemanggilan mengubah satu variabel global yang sama. Perilaku ini mudah digunakan sekaligus mudah menimbulkan masalah, karena seluruh nama global berada dalam satu ruang nama yang sama untuk seluruh program. Dua bagian kode yang tanpa sengaja menggunakan nama jumlah akan saling menimpa nilai, dan penelusuran penyebab perubahannya menjadi sulit karena setiap fungsi berhak mengubahnya.
Variabel lokal dan jangka hidup blok#
Kata local membuat variabel lokal, yaitu variabel yang lahir pada titik deklarasinya dan berakhir pada akhir blok tempat ia dideklarasikan. Blok (block) adalah unit pernyataan yang dibentuk oleh badan berkas, badan pernyataan kendali seperti if dan while, badan fungsi, serta pasangan do dan end yang dibuat khusus. Setelah blok berakhir, variabel lokalnya tidak lagi ada, dan nama yang sama kembali merujuk ke variabel luar apabila ada.
Pasangan do dan end berguna untuk membatasi jangka hidup variabel sementara tanpa membentuk perulangan maupun percabangan. Berkas berikut mendeklarasikan dua variabel pada dua blok berbeda, lalu membaca satu nama yang sudah tidak ada lagi.
-- Variabel lokal hanya hidup di dalam blok yang mendeklarasikannya
local luar = "di luar"
do
local dalam = "di dalam do"
print(dalam)
print(luar)
end
print(dalam)di dalam do
di luar
nilKeluaran nil pada baris ketiga berasal dari pembacaan dalam setelah bloknya berakhir. Nama dalam tidak merujuk ke variabel lokal mana pun, sehingga Lua mencarinya sebagai variabel global yang memang belum pernah diberi nilai. Pola ini merupakan cara sederhana memastikan jangka hidup suatu variabel benar-benar terbatas.
Shadowing dan idiom local x = x#
Deklarasi local dengan nama yang sudah digunakan di blok luar membuat nama baru menutupi (shadowing) nama lama hingga bloknya berakhir. Selama masa penutupan itu, seluruh pembacaan dan penugasan pada nama tersebut menyentuh variabel lokal yang baru, sedangkan variabel luar tetap utuh dan kembali aktif setelah blok berakhir.
-- Nama lokal yang baru menutupi nama luar hingga bloknya berakhir
local konversi = 1000
do
local konversi = konversi
konversi = konversi + 5
print(konversi)
end
print(konversi)1005
1000Keluaran menunjukkan penambahan lima hanya menyentuh variabel lokal di dalam blok, sedangkan variabel luar tetap bernilai 1000. Idiom local x = x memanfaatkan aturan ini untuk mengambil nilai dari cakupan luar ke dalam variabel lokal dengan nama yang sama. Sisi kanan penugasan masih dibaca sebelum nama lokal baru berlaku, sehingga nilai lama tersalin dengan aman pada baris deklarasi itu juga. Idiom ini lazim digunakan di awal fungsi untuk menyalin nilai luar ke lokal sebelum nilai luar dapat berubah di dalam badannya.
Aturan keterlihatan dan urutan deklarasi#
Variabel lokal terlihat dari titik deklarasinya hingga akhir blok, tidak dari awal blok. Kode yang ditulis sebelum deklarasi tidak dapat membaca variabel tersebut, sehingga urutan baris menentukan keterlihatan. Aturan ini membuat Lua dapat menyelesaikan setiap nama pada saat kode dibaca tanpa menebak maksud penulisnya.
Konsekuensi praktisnya muncul pada fungsi. Fungsi mengikat nama menurut kondisi teks pada saat fungsi itu didefinisikan, sehingga variabel lokal yang ingin dibaca harus sudah dideklarasikan sebelum definisi fungsi. Berkas berikut menempatkan deklarasi diskon sebelum fungsi hargaAkhir, sehingga fungsi itu membaca nilai lokal yang benar.
-- Fungsi membaca variabel lokal yang dideklarasikan sebelum definisinya
local diskon = 15
local function hargaAkhir(harga)
return harga - diskon
end
print(hargaAkhir(100))85Apabila urutan deklarasi terbalik, fungsi tidak menemukan variabel lokal yang dimaksud dan pencarian nama jatuh ke variabel global, yang berakhir nil apabila belum pernah diberi nilai. Operasi yang menggunakan nil tersebut memunculkan error saat program berjalan. Memeriksa urutan deklarasi menjadi langkah pertama ketika sebuah fungsi membaca nilai yang tidak diharapkan.
Ringkasan#
- Penugasan tanpa kata
localselalu membuat atau mengubah variabel global, di mana pun penugasan itu ditulis. - Kata
localmembuat variabel yang hidup dari titik deklarasi hingga akhir bloknya, termasuk blokdo...end, badan percabangan dan perulangan, serta badan fungsi. - Shadowing membuat nama lokal baru menutupi nama luar yang sama hingga blok berakhir, dan idiom
local x = xmenyalin nilai luar sebelum penutupan itu berlaku. - Variabel global memperluas permukaan perubahan lintas program, sehingga
localmenjadi pilihan bawaan yang lebih mudah diaudit.
Referensi#
- Referensi Manual Lua 5.4 — Lua.org — Bagian Variables dan Local Declarations mengatur penugasan global serta deklarasi lokal, dan bagian Visibility Rules menetapkan kaidah keterlihatan nama.
- Programming in Lua — Lua.org — Bab pernyataan membahas variabel global, deklarasi lokal, dan blok beserta idiom-idiom cakupannya.