Topik ini membahas mekanisme pengambilan keputusan Erlang: guard sebagai syarat tambahan pada klausul fungsi, case sebagai pencocok pola umum di tengah fungsi, dan if yang bekerja murni dengan guard sequence. Pembahasan ditutup dengan daftar ekspresi yang sah di dalam guard beserta batasannya. Semua transkrip dieksekusi nyata pada OTP 29.
Guard pada klausa fungsi#
Guard adalah syarat boolean yang membatasi kapan sebuah klausa fungsi berlaku. Fungsi dengan guard didefinisikan sebagai rangkaian klausa, dan Erlang mencobanya dari atas ke bawah sampai menemukan pola dan guard yang cocok sekaligus. Modul berikut mengelompokkan hasil pembacaan sensor suhu:
-module(klasifikasi).
-export([suhu/1]).
suhu(S) when is_integer(S), S >= 30 -> panas;
suhu(S) when is_integer(S), S >= 20 -> hangat;
suhu(S) when is_integer(S), S >= 10 -> sejuk;
suhu(S) when is_integer(S), S < 10 -> dingin.Setiap klausa membawa dua syarat yang dipisahkan koma: is_integer(S) menjamin tipe argumennya, dan perbandingan suhu menentukan kelompoknya. Koma berarti logika dan yang menyatukan syarat pada satu guard, sedangkan titik koma antar klausa berarti alternatif atau antar klausa. Hasil eksekusinya:
4> c(klasifikasi).
{ok,klasifikasi}
5> klasifikasi:suhu(35).
panas
6> klasifikasi:suhu(25).
hangat
7> klasifikasi:suhu(15).
sejuk
8> klasifikasi:suhu(5).
dinginUrutan klausa menentukan makna: suhu(35) jatuh ke klausa pertama karena 35 >= 30, sedangkan suhu(25) melewati klausa pertama dan berhenti di klausa kedua. Menyusun syarat dari yang paling ketat ke paling longgar, seperti pada contoh di atas, membuat fungsi terbaca sebagai rentang nilai yang berurutan.
Guard gagal, bukan error#
Apabila tidak ada klausul yang cocok, kegagalan guard bukan bernilai false melainkan memicu error function_clause. Pemanggilan dengan tipe yang salah menunjukkan akibatnya:
9> klasifikasi:suhu(abc).
** exception error: no function clause matching klasifikasi:suhu(abc) (klasifikasi.erl:4)Argumen abc adalah atom, sehingga is_integer(abc) gagal pada keempat klausa dan error no function clause matching muncul beserta nama modul dan barisnya. Guard is_integer/1 pada modul di atas justru sengaja memicu perilaku ini: nilai non-integer dianggap pelanggaran kontrak, bukan kasus bisnis, sehingga lebih tepat dibiarkan gagal daripada dipaksakan masuk ke kelompok mana pun.
case sebagai pencocok umum#
Ekspresi case membawa pencocokan pola dan guard ke dalam tubuh fungsi, bukan hanya pada kepala klausanya. Bentuknya memeriksa satu nilai terhadap rangkaian pola:
1> F = fun(X) -> case X of {ok, N} when N > 10 -> besar; {ok, _} -> kecil; Lain -> {lain, Lain} end end.
#Fun<erl_eval.42.130099583>
2> F({ok, 42}).
besar
3> F({ok, 3}).
kecil
4> F(mist).
{lain,mist}Pola pertama menangkap tuple {ok, N} dengan syarat N > 10, pola kedua menangkap {ok, _} apa pun nilainya, dan pola ketiga memakai variabel Lain sebagai penangkap semua yang tersisa. Hasil ketiga pemanggilan menunjukkan urutan pemeriksaan: {ok, 42} masuk kelompok besar, {ok, 3} masuk kelompok kecil, dan atom mist jatuh ke cabang penangkap. Setiap pola pada case boleh membawa guard-nya sendiri, sehingga keputusan bertingkat tetap terbaca rapi.
if dengan guard sequence#
Ekspresi if adalah bentuk khusus yang hanya berisi guard sequence tanpa pola. Setiap cabang diperiksa dari atas ke bawah, dan guard true berperan sebagai jalan keluar bila semua syarat lain gagal:
5> G = fun(N) -> if N > 0 -> positif; N < 0 -> negatif; true -> nol end end.
#Fun<erl_eval.42.130099583>
6> G(-5).
negatif
7> G(0).
nol
8> G(9).
positifCabang N > 0 dan N < 0 menangani kedua arah, sedangkan true menangkap sisanya, yaitu nol. Berbeda dengan case, ekspresi if tidak menguraikan struktur apa pun, sehingga pilihannya tepat bila keputusan murni bergantung pada perbandingan. Bila tidak ada guard yang benar dan tidak ada cabang true, error if_clause muncul.
Ekspresi yang sah di guard#
Guard bukan tempat yang bebas untuk memanggil fungsi. Daftar ekspresi yang diperbolehkan sengaja dibatasi agar evaluasi guard selalu cepat dan bebas efek samping: perbandingan, aritmetika, fungsi uji tipe seperti is_integer/1 dan is_atom/1, fungsi bawaan pembacaan data seperti element/2 dan hd/1, serta operator andalso, orelse, dan not. Gabungan beberapa syarat ditulis dengan koma untuk dan atau titik koma untuk atau di dalam satu guard.
Batasan paling terasa adalah fungsi buatan sendiri tidak boleh dipanggil di guard. Bila suatu pemeriksaan membutuhkan logika fungsi, pola yang umum adalah menghitung nilainya terlebih dahulu di tubuh fungsi atau pada pemanggil, lalu membandingkan hasilnya di guard dengan perbandingan biasa. Desain ini menjaga klausul fungsi tetap dapat dipilih tanpa mengeksekusi kode yang tidak terduga.
Kesalahan umum#
- Memanggil fungsi buatan sendiri di dalam guard. Kompiler menolaknya sebagai ekspresi guard yang tidak sah, karena guard hanya menerima daftar fungsi bawaan bahasa. Hitung nilainya terlebih dahulu di tubuh fungsi atau pada pemanggil, lalu bandingkan hasilnya di guard.
- Menukar koma dengan titik koma pada definisi klausa. Koma menyatukan syarat dalam satu guard, sedangkan titik koma memisahkan klausa. Tanda yang salah membuat klausa tidak pernah tercapai atau menyatukan syarat yang seharusnya menjadi pilihan, dan gejalanya sering hanya berupa hasil yang tidak masuk akal.
- Menyusun
iftanpa cabang penutup. Bila masukan datang di luar semua guard dan tidak ada cabangtrue, errorif_clausemuncul saat runtime. Cadangkan cabangtruebila nilai di luar dugaan memang diperkenankan, atau pindahkan logikanya kecasedengan pola penangkap.
Ringkasan#
- Guard membatasi klausul fungsi dengan syarat boolean, dan klausa dicoba dari atas ke bawah sampai pola dan guard keduanya cocok.
- Koma berarti dan, titik koma antar klausa berarti alternatif, dan kegagalan semua klausul memicu error function_clause.
- case memeriksa satu nilai terhadap rangkaian pola, dan setiap pola boleh membawa guardnya sendiri.
- if hanya memuat guard sequence dan lazim ditutup cabang true sebagai penangkap sisa.
- Guard hanya menerima ekspresi terbatas tanpa efek samping, dan fungsi buatan sendiri tidak boleh dipanggil di sana.
Referensi#
- Erlang Reference Manual: Expressions — Ericsson — Dokumentasi resmi case, if, dan daftar ekspresi yang sah pada guard.
- Erlang Reference Manual: Patterns — Ericsson — Aturan pola pada kepala klausul dan cabang case.
- Learn You Some Erlang for Great Good! — Fred Hebert — Bab yang memperkenalkan guard, case, dan if beserta kebiasaan pemakaiannya.