Nilai dan Tipe

Delapan tipe dasar Lua, pengetikan dinamis, dan peran khusus nilai nil.

Daftar isi

Topik ini membahas sistem tipe Lua secara menyeluruh, mulai dari kedelapan tipe dasar beserta fungsi type() untuk memeriksanya, pengetikan dinamis, peran khusus nilai nil, aturan nilai kebenaran, dua sub-tipe pada tipe number, hingga konversi otomatis antara string dan number. Setelah menyelesaikannya, perilaku setiap nilai pada operasi aritmetika maupun uji kondisi dapat dijelaskan dengan istilah yang tepat.

Delapan tipe dasar#

Lua hanya memiliki kedelapan tipe dasar berikut, dan tidak ada tipe lain, yaitu nil, boolean, number, string, function, userdata, thread, dan table. Tipe melekat pada nilai, bukan pada variabel, sehingga nilai apa pun dapat diperiksa tipenya di mana pun nilai itu berada. Fungsi type() menerima satu nilai dan mengembalikan nama tipe nilai tersebut dalam bentuk string, misalnya "number" atau "table". Nama table merujuk pada satu tipe tunggal, sehingga seluruh bentuk kumpulan data pada Lua dibangun di atasnya.

Tabel berikut merangkum peran setiap tipe.

TipePeran
nilPenanda ketiadaan nilai
booleanNilai kebenaran true dan false
numberBilangan bulat maupun pecahan
stringUrutan byte 8-bit, umumnya teks
functionFungsi, yang dapat ditampung dan dipindah seperti nilai lain
userdataData milik program host, yaitu aplikasi yang menyematkan Lua
threadAlur eksekusi kooperatif yang dihasilkan coroutine
tableSatu-satunya struktur data Lua untuk seluruh bentuk kumpulan data

Berkas berikut memanggil type() atas satu contoh nilai untuk setiap tipe. Nilai bertipe userdata diambil dari aliran keluaran standar pustaka io, sedangkan nilai bertipe thread diambil dari coroutine, yaitu jalur eksekusi kooperatif yang dapat dihentikan dan dilanjutkan secara terkendali. Perhatikan bahwa 10 dan 3.5 sama-sama dilaporkan sebagai number, karena keduanya berada di dalam tipe yang sama.

lua tipe.lua
-- Memeriksa tipe satu nilai dari setiap tipe dasar Lua
print(type(nil))
print(type(true))
print(type(10))
print(type(3.5))
print(type("Citra"))
print(type(print))
print(type(io.stdout))
print(type(coroutine.create(function() end)))
print(type({90, 85, 78}))
text Keluaran
nil
boolean
number
number
string
function
userdata
thread
table

Pengetikan dinamis#

Lua menerapkan pengetikan dinamis (dynamic typing), yaitu skema yang memeriksa tipe saat program berjalan, bukan saat kode ditulis atau dikompilasi. Akibatnya, variabel tidak memiliki tipe, dan yang memiliki tipe adalah nilai yang sedang ditampungnya. Satu nama variabel boleh menampung number pada satu baris, kemudian menampung string atau nil pada baris berikutnya, tanpa deklarasi maupun konversi apa pun.

Fleksibilitas ini menuntut kehati-hatian yang seimbang. Kesalahan tipe tidak tertangkap saat kode ditulis, melainkan baru muncul saat program berjalan. Kebiasaan yang menjaga kejelasan adalah memeriksa tipe nilai yang berasal dari luar fungsi sendiri dengan type() sebelum nilai itu diolah lebih lanjut.

Berkas berikut mengganti isi satu variabel dua kali, lalu menanyakan tipenya pada setiap tahap.

lua Contoh: satu variabel menampung tipe berbeda
-- Satu variabel menampung nilai bertipe berbeda sepanjang hidupnya
local skor = 90
print(type(skor))
skor = "sembilan puluh"
print(type(skor))
skor = nil
print(type(skor))
text Keluaran
number
string
nil

Nilai balik type() berupa string, sehingga pemeriksaan tipe dapat dilakukan dengan perbandingan biasa tanpa pustaka tambahan.

lua Contoh: pemeriksaan tipe dengan perbandingan string
-- Nilai balik type() berupa string sehingga dapat dibandingkan langsung
local skor = 90
if type(skor) == "number" then
  print("skor berupa bilangan")
end
text Keluaran
skor berupa bilangan

Peran khusus nil#

nil adalah satu-satunya nilai pada satu-satunya tipenya, dan tipe ini berperan sebagai penanda ketiadaan nilai (absence of value). Setiap variabel yang belum diberi nilai bernilai nil, dan penugasan nil kepada suatu variabel menghapus nilai yang lama. Fungsi print() menampilkan teks nil untuk nilai ini, sehingga ketiadaan nilai memperoleh nama yang terlihat hanya pada saat ditampilkan.

lua Contoh: variabel tanpa penugasan bernilai nil
-- Variabel yang belum diberi nilai tetap bernilai nil
local catatan
print(catatan)
text Keluaran
nil

Peran kedua nil adalah menghapus pasangan kunci-nilai dari sebuah table. Penugasan nil kepada satu kunci membuat kunci tersebut tidak lagi ada di dalam table, berbeda dari menyimpan nilai yang tidak berguna. Berkas berikut menghapus satu jadwal dari sebuah table.

lua Contoh: penugasan nil menghapus kunci table
-- Penugasan nil menghapus pasangan kunci-nilai dari sebuah table
local jadwal = { senin = "Matematika", selasa = "Fisika" }
jadwal.senin = nil
print(jadwal.senin)
print(jadwal.selasa)
text Keluaran
nil
Fisika

Keluaran menunjukkan jadwal.senin tidak lagi memiliki nilai, sedangkan kunci lain tetap utuh. Peran ketiga muncul pada fungsi, yaitu fungsi yang berakhir tanpa pernyataan return tidak mengembalikan nilai apa pun, dan nilai yang hilang itu menjadi nil apabila ditempatkan ke dalam variabel.

lua Contoh: fungsi tanpa return menghasilkan nil
-- Fungsi tanpa return tidak mengembalikan nilai apa pun
local function catat(pesan)
  print(pesan)
end

local balikan = catat("rapat dimulai")
print(balikan)
text Keluaran
rapat dimulai
nil

Nilai kebenaran dalam uji kondisi#

Dalam uji kondisi, Lua menganggap hanya nil dan false sebagai nilai palsu (falsy), sedangkan nilai lain semuanya benar. Aturan ini berbeda dari banyak bahasa lain yang menganggap nol atau string kosong sebagai nilai palsu. Akibatnya, 0, string kosong "", dan table kosong tetap lolos pengujian sebagai nilai benar.

Berkas berikut menguji tiga nilai yang berbeda-beda terhadap pernyataan if.

lua Contoh: 0 dan string kosong tetap dianggap benar
-- Hanya nil dan false yang palsu, sisanya benar dalam uji kondisi
local jumlah = 0
if jumlah then
  print("nol dianggap benar")
end

local nama = ""
if nama then
  print("string kosong dianggap benar")
end

local catatan = nil
if not catatan then
  print("nil dianggap palsu")
end
text Keluaran
nol dianggap benar
string kosong dianggap benar
nil dianggap palsu

Aturan ini menjelaskan pola umum pada pustaka Lua, yaitu mengembalikan nil untuk menyatakan ketiadaan hasil. Pencarian yang gagal mengembalikan nil, sehingga hasilnya langsung dapat diuji dengan if hasil then tanpa perbandingan tambahan. Pola yang sama membuat false dan nil dapat ditulis sebagai satu kelas pengujian, namun nilai lain tetap harus diperiksa tipenya apabila pembagiannya diperlukan.

Tipe number: integer dan float#

Sejak Lua 5.4, tipe number terbagi menjadi dua sub-tipe, yaitu integer untuk bilangan bulat 64 bit dan float untuk bilangan pecahan presisi ganda. Keduanya merupakan satu tipe number yang sama, tetapi fungsi math.type() dapat membedakannya dan mengembalikan teks "integer" atau "float". Nilai 3.0 dan 3 bernilai sama menurut perbandingan kesamaan, namun sub-tipenya berbeda.

lua Contoh: membedakan integer dan float dengan math.type
-- math.type membedakan dua sub-tipe number
print(math.type(1))
print(math.type(1.0))
print(3.0 == 3)
text Keluaran
integer
float
true

Perbedaan sub-tipe memengaruhi hasil aritmetika. Pembagian biasa dengan operator / selalu menghasilkan float, sedangkan pembagian bulat dengan operator // menghasilkan bilangan bulat apabila kedua operannya bulat. Dua operator ini menangani kebutuhan yang berbeda, yaitu perhitungan pecahan dan pembagian yang hasilnya harus berupa bilangan bulat.

lua Contoh: pembagian biasa dan pembagian bulat
-- Pembagian / selalu menghasilkan float, sedangkan // membulatkan ke bawah
print(7 / 2)
print(7 // 2)
print(-7 // 2)
text Keluaran
3.5
3
-4

Keluaran menunjukkan 7 / 2 menghasilkan 3.5, sedangkan 7 // 2 menghasilkan 3 dan -7 // 2 menghasilkan -4. Pembulatan // mengikuti arah bilangan bulat terdekat yang lebih kecil, sehingga hasil untuk -7 turun ke -4 dan bukan naik ke -3. Nilai 3 tanpa bagian desimal pada keluaran menandakan sub-tipe integer, sedangkan 3.5 dan keluaran dengan bagian desimal menandakan float.

Konversi otomatis antartipe#

Lua melakukan coercion, yaitu konversi tipe otomatis pada operasi tertentu. Dalam operasi aritmetika, Lua mencoba mengubah string menjadi number, dan dalam penyambungan string, Lua mengubah number menjadi string. Konversi ini terjadi pada tingkat operasi, bukan pada nilai itu sendiri, sehingga nilai aslinya tidak berubah.

lua Contoh: konversi otomatis pada aritmetika dan penyambungan
-- Lua mengonversi string dan number secara otomatis pada operasi tertentu
print("10" + 1)
print("3.5" * 2)
print("Nilai: " .. 95)
text Keluaran
11
7.0
Nilai: 95

Keluaran menunjukkan "10" + 1 menghasilkan 11, "3.5" * 2 menghasilkan 7.0, dan penyambungan "Nilai: " .. 95 menghasilkan teks Nilai: 95. Kemudahan ini nyaman, tetapi konversi eksplisit dengan tonumber dan tostring menyatakan maksud dengan lebih jelas serta memisahkan pemeriksaan nilai dari operasinya.

lua Contoh: konversi eksplisit dengan tonumber dan tostring
-- Konversi eksplisit menyatakan maksud dengan lebih jelas
print(tonumber("10") + 5)
print(math.type(tonumber("10")))
print(tostring(95) .. " poin")
text Keluaran
15
integer
95 poin

Ringkasan#

  • Lua memiliki delapan tipe dasar, dan type() mengembalikan nama tipe sebuah nilai dalam bentuk string.
  • Pengetikan dinamis menempelkan tipe pada nilai, bukan pada variabel, sehingga satu variabel boleh menampung tipe yang berbeda dari waktu ke waktu.
  • nil menandai ketiadaan nilai, menghapus kunci table, dan menjadi hasil dari fungsi tanpa return.
  • Hanya nil dan false yang palsu dalam uji kondisi, number terbagi menjadi integer dan float, dan coercion mengubah tipe secara otomatis pada aritmetika serta penyambungan.

Referensi#

  • Referensi Manual Lua 5.4 — Lua.org — Bagian Values and Types mendefinisikan kedelapan tipe dasar, sedangkan bagian Coercions and Conversions mengatur konversi otomatis antara string dan number.
  • Programming in Lua — Lua.org — Buku pegangan resmi Lua yang ditulis arsitek utamanya, dengan bab-bab awal memperkenalkan tipe nilai, angka, dan pengetikan dinamis.