Program berinteraksi dengan lingkungan eksekusinya melalui argumen command line, variabel lingkungan, dan exit code. Topik ini membahas pembacaan argumen melalui getArgs dan getProgName, pembacaan variabel lingkungan (environment variable) melalui lookupEnv, serta penetapan exit code melalui exitWith. Setelah membacanya, program dapat menerima pengaturan dari luar dan melaporkan keberhasilannya kepada perangkat lain yang memanggilnya.
Argumen command line#
getArgs :: IO [String] mengembalikan argumen yang diketik setelah nama program, sedangkan getProgName :: IO String mengembalikan nama program itu sendiri. Keduanya berada pada modul System.Environment yang diimpor di awal berkas. Program berikut menyapa argumen pertamanya beserta nama programnya, dan apabila tidak ada argumen, program menampilkan petunjuk penggunaan yang menuliskan cara pemanggilannya secara harfiah.
import System.Environment (getArgs, getProgName)
main :: IO ()
main = do
namaProgram <- getProgName
argumen <- getArgs
case argumen of
[] -> putStrLn "Pemakaian: runghc sapa-argumen.hs NAMA"
(nama:_) -> putStrLn ("Halo, " ++ nama ++ "! (program " ++ namaProgram ++ ")")Pemakaian: runghc sapa-argumen.hs NAMAArgumen baru muncul apabila program dijalankan dengan tambahan kata pada perintahnya.
# jalankan program dengan satu argumen
runghc sapa-argumen.hs Ali
# jalankan lagi dengan argumen berbeda
runghc sapa-argumen.hs BudiHalo, Ali! (program sapa-argumen.hs)
Halo, Budi! (program sapa-argumen.hs)Pencocokan pola pada case memilah dua keadaan tersebut, yaitu list kosong untuk petunjuk penggunaan dan list berisi minimal satu elemen untuk sapaan. Nama program pada sapaan berasal dari getProgName, sehingga pesan sapaannya mengikuti nama berkas yang dipanggil, sedangkan baris petunjuknya ditulis harfiah agar tetap stabil meskipun berkasnya dinamai ulang. Ketika program dikompilasi menjadi biner, getProgName menampilkan nama tanpa akhiran .hs, sedangkan pada runghc akhiran itu ikut tampil karena program dipanggil melalui berkas sumbernya.
Lebih dari satu argumen dapat diolah sebagaimana list biasa, misalnya dipetakan dan dijumlahkan melalui fungsi murni sebelum dicetak. Pemisahan ini mengikuti kebiasaan jalur ini, yaitu pembacaan argumen menjadi tepi IO yang tipis, sedangkan seluruh penalaran atas isinya berlangsung murni. Fungsi yang menerima [String] dan menghasilkan String dapat diuji tanpa menyentuh IO sama sekali, sehingga pengujian pengolahan argumen menjadi pekerjaan fungsi biasa.
Variabel lingkungan#
Variabel lingkungan (environment variable) adalah pasangan nama dan nilai yang disediakan shell kepada program, misalnya PATH. Fungsi lookupEnv :: String -> IO (Maybe String) mencarinya dengan aman, yaitu menghasilkan Just berisi nilai apabila variabelnya diatur dan Nothing apabila tidak. Bentuk Maybe ini menjadikan keadaan tidak diatur sebagai bagian dari tipe, sehingga pencocokan pola menuntut agar kedua keadaan diperlakukan.
import System.Environment (lookupEnv)
main :: IO ()
main = do
modus <- lookupEnv "MODUS_TAMPIL"
case modus of
Nothing -> putStrLn "MODUS_TAMPIL tidak diatur, modus normal dipakai"
Just teks -> putStrLn ("MODUS_TAMPIL berisi " ++ teks)MODUS_TAMPIL tidak diatur, modus normal dipakaiAwalan penugasan pada shell mengatur variabel hanya untuk satu perintah, sehingga program yang sama menghasilkan cabang Just tanpa mengubah shell keseluruhan.
# atur variabel lingkungan hanya untuk perintah ini
MODUS_TAMPIL=ringkas runghc baca-lingkungan.hsMODUS_TAMPIL berisi ringkasPola dua cabang seperti ini lazim pada program yang perilakunya diatur dari luar, misalnya memilih tingkat keterangan yang dicetak. Variabel dengan nama khusus aplikasi dipilih sebagai contoh agar keluarannya deterministik, karena variabel bawaan sistem berbeda antara satu mesin dan mesin lain.
Perbedaan antara argumen dan variabel lingkungan terletak pada jangkauan penyampaiannya. Argumen berlaku untuk satu pemanggilan program dan terlihat pada perintahnya, sedangkan variabel lingkungan diatur pada shell dan diwariskan kepada setiap program yang dimulai darinya, sehingga cocok untuk pengaturan yang berlaku lintas perintah. Keduanya tiba sebagai String, sehingga angka dan bentuk lain tetap melalui penguraian yang sama dengan masukan berkas.
Exit code program#
Exit code adalah bilangan yang disampaikan program kepada shell ketika berakhir, dengan konvensi nol untuk sukses dan selain nol untuk kegagalan. Nilai ini menjadi cara program berbicara dengan alat lain, misalnya skrip yang memutuskan langkah berikutnya berdasarkan keberhasilan perintah sebelumnya. Haskell menyediakannya melalui tipe ExitCode pada modul System.Exit, dan exitWith menghentikan program dengan kode yang diminta.
import System.Exit (ExitCode(..), exitWith)
main :: IO ()
main = do
putStrLn "Pemrosesan antrian dihentikan"
exitWith (ExitFailure 2)Pemrosesan antrian dihentikanShell menyimpan kode keluar perintah terakhir pada variabel khusus $?, sehingga bilangan yang ditetapkan program dapat diperiksa langsung setelah program berjalan.
# jalankan program yang berhenti dengan kode keluar 2
runghc keluar-kesalahan.hs
# tampilkan kode keluar perintah sebelumnya
echo $?Pemrosesan antrian dihentikan
2Program mencetak satu baris lalu berhenti melalui exitWith (ExitFailure 2), dan shell menampung bilangan tersebut untuk echo $?. Konstruktor ExitSuccess tersedia untuk keadaan sukses, sedangkan exitFailure merupakan singkatan dari exitWith (ExitFailure 1). Perlu dicatat bahwa main yang berakhir tanpa exitWith sama sekali dilaporkan sukses oleh shell, karena kode keluar bawaannya nol.
Kesalahan umum#
Kesalahan yang lazim berupa memanggil getEnv, varian lookupEnv yang lebih tua, pada variabel yang tidak diatur. Alih-alih menghasilkan Maybe, fungsi ini melempar exception sehingga program berhenti tanpa kesempatan menangani keadaan kosong tersebut.
# ambil variabel lingkungan yang tidak pernah diatur
ghci -e 'System.Environment.getEnv "VARIABEL_TAK_ADA"'<interactive>: VARIABEL_TAK_ADA: getEnv: does not exist (no environment variable)Pesan does not exist (no environment variable) menunjukkan kegagalan pencarian, dan kegagalan semacam ini mudah muncul karena isi lingkungan berbeda antara mesin. Perbaikannya berupa menggunakan lookupEnv dan menangani Nothing secara eksplisit, sebagaimana program pada bagian Variabel lingkungan.
Kesalahan kedua berupa lupa bahwa program yang sukses pun membawa exit code. Program yang berhenti di tengah jalan tanpa exitWith tetap dilaporkan sukses oleh shell, sehingga skrip yang mengandalkan kode keluar tidak mengetahui adanya kegagalan. Apabila program memiliki keadaan gagal yang nyata, kode keluar yang sesuai perlu ditetapkan secara eksplisit pada jalur kegagalan tersebut.
Ringkasan#
getArgsmengembalikan argumen command line sebagai listString, dangetProgNamemengembalikan nama program sebagaimana program itu dipanggil.lookupEnvmembaca variabel lingkungan dan menghasilkanMaybe String, sehingga keadaan tidak diatur ditangani melalui pencocokan pola.exitWith (ExitFailure n)menghentikan program dengan kode keluar selain nol, sedangkan program yang berakhir normal membawa kode nol.- Kode keluar dan keberhasilan pencarian variabel merupakan bagian dari antarmuka program menuju shell dan alat lainnya.
Referensi#
- System.Environment — Hackage
— Dokumentasi modul yang memuat
getArgs,getProgName, danlookupEnv. - System.Exit — Hackage
— Dokumentasi tipe
ExitCodebesertaexitWithdanexitFailure. - base package — Hackage — Dokumentasi pustaka standar yang menyediakan modul lingkungan dan exit code.