Topik ini membahas nilai-nilai tunggal Clojure, yaitu angka, string, nil, boolean, dan keyword beserta aturan evaluasinya. Masing-masing tipe dibahas dari cara penulisannya, tipe host yang menampungnya, hingga kebiasaan fungsi inti terhadapnya. Setelah topik ini selesai, pilihan tipe untuk data dasar dapat ditentukan dengan tepat, termasuk keputusan antara string dan keyword untuk penanda kategori.
Angka: long, double, dan ratio#
Bilangan bulat tanpa tanda titik dibaca sebagai long, yaitu tipe bilangan bulat 64-bit milik JVM, sedangkan bilangan bertitik dibaca sebagai double. Pembagian dua bilangan bulat dengan fungsi / tidak memotong sisanya, melainkan menghasilkan ratio, yakni bilangan pecahan eksak berupa perbandingan dua bilangan bulat. Ketelitian eksak inilah yang membuat (+ 1/2 1/3) bernilai tepat 5/6 tanpa pembulatan. Fungsi type memperlihatkan tipe host yang menampung setiap nilai, dan hasilnya membuktikan bahwa angka Clojure adalah angka Java.
; bilangan bulat default bertipe long
(println 42)
(println (type 42))
; pecahan bertitik bertipe double
(println 3.14)
(println (type 3.14))
; ratio menjaga ketelitian penuh
(println 22/7)
(println (+ 1/2 1/3))
(println (type 22/7))42
java.lang.Long
3.14
java.lang.Double
22/7
5/6
clojure.lang.RatioPilihan antara ketiganya mengikuti kebutuhan data. Bilangan hitungan, jumlah item, dan indeks menggunakan long karena nilainya memang bulat. Pengukuran seperti berat dan suhu menggunakan double karena nilainya kontinu dan pembulatan dapat diterima. Ratio digunakan apabila ketelitian pecahan wajib dijaga, misalnya pembagian yang tidak menghasilkan bilangan bulat, dan dapat dikonversi ke double dengan fungsi double apabila bentuk desimalnya diperlukan.
String sebagai java.lang.String#
String ditulis dalam tanda kutip ganda dan menjadi objek java.lang.String pada JVM, sehingga seluruh kebiasaan string Java berlaku padanya. Tanda kutip tunggal bukan pembatas string di Clojure, melainkan singkatan dari bentuk quote. Fungsi str menggabungkan argumen apa pun menjadi satu string dengan mengonversi angka dan nilai lain secara otomatis, sedangkan count menghitung jumlah karakter.
; string ditulis dalam tanda kutip ganda
(println "Belajar Clojure")
(println (type "Belajar Clojure"))
; str menggabungkan dan mengonversi nilai menjadi string
(println (str "Nilai: " 88))
(println (count "kata"))
(println (str "Suhu: " 30.5 " derajat"))Belajar Clojure
java.lang.String
Nilai: 88
4
Suhu: 30.5 derajatString bersifat immutable, sehingga setiap operasi pengolahan mengembalikan string baru dan string aslinya tetap utuh. Perilaku ini sejalan dengan koleksi Clojure lainnya dan membuat string aman digunakan sebagai kunci atau bagian data yang dibagikan ke banyak tempat. Apabila string perlu diurai atau diubah bentuknya, fungsinya berada di namespace clojure.string yang diimpor dengan require terlebih dahulu, sedangkan penggabungan dan penghitungan seperti pada contoh cukup ditangani fungsi inti.
nil dan boolean#
Nilai nil menyatakan ketiadaan nilai, dan predikat nil? menguji apakah sebuah nilai adalah nil. Selain itu terdapat dua nilai boolean, yaitu true dan false, dengan predikat berakhiran tanda tanya seperti boolean? untuk menguji tipenya. Pada logika Clojure hanya ada dua nilai palsu, yaitu nil dan false, sedangkan semua nilai lain dianggap benar, termasuk 0 dan string kosong.
; nil menyatakan ketiadaan nilai
(println nil)
(println (nil? nil))
(println (nil? 0))
(println (nil? ""))
; sejumlah fungsi inti menoleransi nil, kebiasaan nil punya
(println (count nil))
(prn (str nil))
(println (get {:nilai 90} :tidak-ada))
; hanya nil dan false yang dianggap palsu
(println (if 0 :benar :palsu))
(println (if false :benar :palsu))nil
true
false
false
0
""
nil
:benar
:palsuSejumlah fungsi inti menoleransi nil sebagai argumen dengan hasil yang tetap bermakna. Fungsi count mengembalikan 0, fungsi str mengembalikan string kosong, dan get pada kunci yang tidak ada mengembalikan nil. Pola ini dikenal sebagai nil punning, yakni kebiasaan fungsi inti memperlakukan nil sebagai nilai yang wajar alih-alih memicu error. Pendekatan tersebut mengurangi percabangan pemeriksaan nil yang berulang, karena pemeriksaan tinggal dilakukan sekali pada ujung alur data.
Keyword sebagai penanda enumerasi#
Keyword ditulis dengan mengawali namanya dengan :, seperti :status, dan mengevaluasi ke dirinya sendiri. Dua keyword dengan nama sama selalu identik, sehingga perbandingannya murah dan pasti. Peran utamanya adalah penanda enumerasi, yaitu label kategori yang tetap seperti status transaksi atau kunci map. Keyword bukan teks yang perlu dipotong dan digabung, melainkan penanda tetap yang dapat dibandingkan melalui identitasnya.
; keyword mengevaluasi ke dirinya sendiri
(println :status)
(println (type :status))
(println (= :status :status))
(println (= :status "status"))
; keyword dibuat dari string dengan fungsi keyword
(println (keyword "nama"))
(println (= :nama (keyword "nama")))
; keyword berlaku sebagai fungsi pencari pada map
(def transaksi {:jenis "pembelian" :jumlah 3})
(println (:jenis transaksi))
(println (:jumlah transaksi))
(println (:diskon transaksi)):status
clojure.lang.Keyword
true
false
:nama
true
pembelian
3
nilFungsi keyword membuat keyword dari string, sehingga data dari luar yang berupa teks dapat diubah menjadi penanda. Keyword juga berlaku sebagai fungsi yang menerima map dan mengembalikan nilai kuncinya, sehingga (:jenis transaksi) adalah cara akses yang paling ringkas. Apabila kunci tidak ada, hasilnya nil, dan perilaku itu dimanfaatkan untuk pemeriksaan kehadiran kunci.
Bentuk ::nama membuat keyword dengan namespace, yaitu nama yang dilengkapi konteks namespace saat pembacaan. Pada skrip tanpa deklarasi ns, namespace saat itu bernama user, sehingga ::nama setara dengan :user/nama. Pada berkas proyek yang memiliki deklarasi ns, konteksnya mengikuti namespace berkas tersebut. Karena itu, nilai persisnya bergantung pada tempat penulisannya, dan sifat ini membuat penanda tetap unik lintas berkas tanpa risiko tabrakan nama.
Kesalahan umum#
Menggunakan string sebagai penanda kategori. Pembandingan string bergantung pada isi teksnya, sedangkan keyword adalah penanda tetap yang identik di mana pun digunakan. Akibat penggunaan string adalah perbandingan yang lebih mahal dan risiko ketidakcocokan karena perbedaan huruf besar-kecil. Perbaikannya dengan menggunakan keyword untuk kategori dan menyisakan string untuk teks yang isinya benar-benar bervariasi.
Menulis pecahan dengan koma seperti 3,14. Koma dianggap spasi oleh reader, sehingga bentuk itu dibaca sebagai dua nilai terpisah dan memicu error yang tampak tidak masuk akal. Perbaikannya dengan menggunakan titik desimal, yaitu 3.14, karena aturan penulisan Clojure mengikuti konvensi bahasa pemrograman, bukan konvensi tanda desimal Indonesia.
Menganggap nil sama dengan false dalam semua konteks. Keduanya sama-sama dianggap palsu pada logika, tetapi nil? hanya bernilai true untuk nil, dan sejumlah operasi yang mengharapkan boolean akan error menerima nil. Perbaikannya dengan menentukan makna yang diinginkan, yaitu gunakan nil? untuk menguji ketiadaan nilai dan gunakan predikat yang tepat untuk menguji isi.
Ringkasan#
- Bilangan bulat menjadi long, pecahan bertitik menjadi double, dan pembagian bilangan bulat menghasilkan ratio yang eksak.
- String adalah java.lang.String yang ditulis dalam tanda kutip ganda dan bersifat immutable.
- nil menyatakan ketiadaan nilai, dan fungsi inti menoleransi nil sesuai pola nil punning.
- Hanya nil dan false yang dianggap palsu, sedangkan nilai lain termasuk 0 dianggap benar.
- Keyword adalah penanda enumerasi yang mengevaluasi ke dirinya sendiri dan berlaku sebagai fungsi pencari pada map.
Referensi#
- Learn Clojure — Clojure — Panduan resmi tipe data dasar, termasuk angka, string, dan keyword.
- The Reader — Clojure — Aturan penulisan literal angka, string, dan keyword pada teks sumber.
- clojure.core/keyword — ClojureDocs — Contoh penggunaan fungsi keyword beserta catatan komunitasnya.