Fungsi dan prosedur

Pembedaan fungsi dan prosedur beserta mode parameter in, out, dan in out.

Daftar isi

Subprogram adalah unit program bernama yang dapat dipanggil berulang kali, dan Ada membaginya menjadi dua bentuk, yaitu prosedur dan fungsi. Topik ini membahas pembedaan kedua bentuk tersebut, tiga parameter mode yang mengatur arah aliran data, serta perancangan antarmuka subprogram yang aliran datanya jelas. Contoh yang dapat dikompilasi dan dijalankan menggunakan perhitungan konversi suhu, penghitung sederhana, dan pembagian bilangan bulat dengan sisa.

Prosedur dan fungsi#

Prosedur dideklarasikan dengan kata procedure dan dipanggil sebagai pernyataan, sedangkan fungsi dideklarasikan dengan kata function dan dipanggil di dalam ekspresi. Setiap fungsi wajib mengembalikan tepat satu nilai, ditandai dengan klausa return pada deklarasinya. Pembedaan ini ditegakkan saat kompilasi, karena Ada melarang pemanggilan fungsi sebagai pernyataan. Jika hasil pemanggilan fungsi tidak digunakan, kompilator menolak program tersebut, sehingga tidak ada nilai kembali yang hilang tanpa sengaja.

Deklarasi prosedur dan fungsi memiliki bentuk yang mirip, yaitu kepala subprogram diikuti badan yang diapit kata begin dan end.

ada Bentuk deklarasi prosedur dan fungsi
procedure Tampilkan_Menu is
begin
   Put_Line ("1. Konversi suhu");
   Put_Line ("2. Keluar");
end Tampilkan_Menu;

function Celsius_Ke_Fahrenheit (Celsius : in Integer) return Integer is
begin
   return Celsius * 9 / 5 + 32;
end Celsius_Ke_Fahrenheit;

Untuk fungsi yang isinya hanya satu ekspresi, Ada 2012 menyediakan expression function, yaitu bentuk yang menuliskan badan fungsi sebagai satu ekspresi setelah kata is. Bentuk ini memperpendek deklarasi dan digunakan secara luas pada penulisan kontrak subprogram.

ada Contoh: expression function
function Terbesar (A, B : in Integer) return Integer is
  (if A > B then A else B);

Mode parameter in, out, dan in out#

Setiap parameter membawa mode, disebut parameter mode, yang menentukan arah aliran datanya. Terdapat tiga mode, dan mode in menjadi pilihan bawaan apabila mode tidak ditulis. Tabel berikut merangkum arti ketiganya.

ModeArah aliran dataKewajiban pada badan subprogram
innilai masuk ke subprogramhanya boleh dibaca
outnilai keluar dari subprogramwajib diisi sebelum dibaca
in outnilai masuk, diproses, lalu keluarboleh dibaca dan ditulis ulang

Parameter mode in diperlakukan seperti konstanta di dalam badan subprogram, sehingga setiap penugasan kepadanya ditolak saat kompilasi. Parameter mode out dianggap belum bernilai pada saat masuk, sehingga nilainya baru dapat dibaca setelah diisi. Parameter mode in out membawa nilai awal ke dalam subprogram, dan nilai akhirnya terbawa keluar pada saat subprogram kembali. Satu-satunya pengecualian ada pada fungsi, yang hanya boleh memiliki parameter mode in karena keluarannya memang dinyatakan sebagai nilai kembali.

Contoh program dengan tiga mode#

Program berikut memuat empat subprogram, yaitu prosedur tanpa parameter, fungsi dengan mode in, prosedur dengan mode in out, dan prosedur dengan dua mode out. Kompilasi menggunakan gnatmake, dan program hasilnya dijalankan tanpa argumen.

ada mode_parameter.adb
with Ada.Text_IO; use Ada.Text_IO;

procedure Mode_Parameter is

   -- Prosedur tanpa parameter: dipanggil sebagai pernyataan.
   procedure Cetak_Pemisah is
   begin
      Put_Line ("--------------------");
   end Cetak_Pemisah;

   -- Fungsi dengan parameter mode in: nilai hanya dibaca.
   function Celsius_Ke_Fahrenheit (Celsius : in Integer) return Integer is
   begin
      return Celsius * 9 / 5 + 32;
   end Celsius_Ke_Fahrenheit;

   -- Prosedur dengan mode in out: nilai masuk dan kembali berubah.
   procedure Majukan_Penghitung (Penghitung : in out Integer;
                                 Langkah   : in Integer) is
   begin
      Penghitung := Penghitung + Langkah;
   end Majukan_Penghitung;

   -- Prosedur dengan dua mode out: menghasilkan dua nilai sekaligus.
   procedure Sisa_Bagi (Nilai, Pembagi : in Integer;
                        Hasil, Sisa   : out Integer) is
   begin
      Hasil := Nilai / Pembagi;
      Sisa  := Nilai rem Pembagi;
   end Sisa_Bagi;

   Penghitung : Integer := 0;
   Hasil      : Integer;
   Sisa       : Integer;

begin
   Cetak_Pemisah;
   Put_Line ("25 derajat Celsius = "
             & Integer'Image (Celsius_Ke_Fahrenheit (25))
             & " derajat Fahrenheit");
   Cetak_Pemisah;
   Majukan_Penghitung (Penghitung, 3);
   Majukan_Penghitung (Penghitung, 2);
   Put_Line ("Penghitung setelah dua pemanggilan:"
             & Integer'Image (Penghitung));
   Cetak_Pemisah;
   Sisa_Bagi (17, 5, Hasil, Sisa);
   Put_Line ("17 : 5 memberikan hasil" & Integer'Image (Hasil)
             & " dan sisa" & Integer'Image (Sisa));
end Mode_Parameter;
bash
# kompilasi dengan flag -gnata agar pemeriksaan run time aktif
gnatmake -q -gnata mode_parameter.adb
# jalankan program hasil kompilasi
./mode_parameter
text Keluaran
--------------------
25 derajat Celsius =  77 derajat Fahrenheit
--------------------
Penghitung setelah dua pemanggilan: 5
--------------------
17 : 5 memberikan hasil 3 dan sisa 2

Fungsi Celsius_Ke_Fahrenheit menerima satu nilai mode in dan mengembalikan satu nilai, sehingga pemanggilannya berada di dalam ekspresi pada Put_Line. Prosedur Majukan_Penghitung menerima parameter Penghitung dengan mode in out, dan nilainya bertambah pada setiap pemanggilan. Prosedur Sisa_Bagi mengisi dua parameter out sekaligus, yaitu Hasil dan Sisa, sehingga pemanggil tidak perlu menghitung sisa bagi sendiri. Urutan argumen pada pemanggilan wajib sama dengan urutan parameter pada deklarasi, kecuali pemanggilan menggunakan bentuk bernama seperti Sisa_Bagi (Nilai => 17, Pembagi => 5, Hasil => Hasil, Sisa => Sisa).

Pemanggilan bernama dan overloading#

Pemanggilan bernama (named association) menyandingkan setiap argumen dengan nama parameternya melalui =>, sehingga urutan penulisannya bebas dan makna tiap argumen terbaca langsung pada tempat pemanggilan. Bentuk ini sangat berguna pada subprogram dengan banyak parameter bertipe sama, sebab pemanggilan posisional seperti Sisa_Bagi (17, 5, Hasil, Sisa) memaksa pembaca membuka deklarasi untuk mengetahui arti tiap angka. Kedua bentuk boleh dicampur pada satu pemanggilan, dengan bagian posisional di depan, tetapi sebuah program sebaiknya menggunakan satu gaya secara konsisten. Pemanggilan bernama juga mengurangi risiko kesalahan urutan argumen, karena dua argumen bertipe sama yang tertukar langsung terlihat pada tempat pemanggilan.

Ada juga mengizinkan dua subprogram menggunakan nama yang sama, selama daftar parameternya dapat dibedakan, dan kebiasaan ini disebut overloading. Kompilator memilih versi yang tepat berdasarkan tipe argumen pada setiap pemanggilan, misalnya Konversi untuk Integer dan Konversi untuk Float sebagai dua subprogram terpisah dengan satu nama. Operator dasar pun dapat di-overload untuk tipe baru, sehingga penjumlahan pada tipe vektor buatan sendiri ditulis dengan tanda + yang sama. Jika pemilihan versi tidak dapat dipastikan karena dua versi sama-sama cocok, kompilator menolak pemanggilan itu sebagai pemanggilan ambigu, dan penulisannya perlu diperjelas dengan kualifikasi atau tanda kurung.

Kesalahan umum#

  • Membaca parameter out sebelum diisi. Pada tipe skalar, nilai parameter out belum terdefinisi pada saat masuk, sehingga pembacaan sebelum penugasan menghasilkan nilai yang tidak dapat diprediksi. Perbaikannya, isi seluruh parameter out lebih dahulu, atau ubah modenya menjadi in out apabila nilai awal memang diperlukan.
  • Memanggil fungsi sebagai pernyataan. Kebiasaan dari bahasa lain seperti C atau Python adalah menulis pemanggilan fungsi dan membuang hasilnya. Ada menolak bentuk tersebut saat kompilasi. Perbaikannya, gunakan hasilnya di dalam ekspresi, atau ubah fungsi menjadi prosedur jika tidak ada nilai yang dikembalikan.
  • Lupa nilai kembali pada salah satu jalur eksekusi fungsi. Jika ada jalur yang tidak mencapai return, kompilator menolak fungsi tersebut. Perbaikannya, pastikan setiap jalur eksekusi mengembalikan nilai, atau susun badan sebagai expression function agar satu ekspresi mewakili seluruh jalur.

Ringkasan#

  • Prosedur dipanggil sebagai pernyataan, sedangkan fungsi dipanggil di dalam ekspresi dan wajib mengembalikan satu nilai.
  • Mode in hanya boleh dibaca dan menjadi pilihan bawaan, mode out wajib diisi sebelum dibaca, dan mode in out membaca lalu menulis ulang.
  • Fungsi hanya menerima parameter mode in, sehingga seluruh data keluar pada prosedur tampak jelas pada deklarasinya.

Referensi#