Parameter formal

Parameter formal berupa tipe berkendala, subprogram, dan package.

Daftar isi

Bagian generic pada unit generik dapat memuat lebih dari satu jenis parameter formal (formal parameter), yaitu tipe berkendala, subprogram, dan package. Kendala yang dituliskan pada parameter formal menentukan operasi apa saja yang tersedia di dalam badan generik dan tipe aktual apa saja yang sah saat instansiasi. Topik ini membahas ragam kendala tipe formal, penyuntikan operasi melalui parameter formal subprogram, penyuntikan package melalui parameter formal package, serta kesalahan instansiasi yang sering terjadi. Contoh yang digunakan adalah pengurutan pembacaan sensor suhu dengan dua kriteria urutan yang berbeda.

Ragam kendala pada tipe formal#

Tipe formal berkendala dinyatakan dengan bentuk yang menjamin operasi minimal di dalam badan generik. Semakin kaya kendalanya, semakin banyak operasi yang dapat digunakan secara bebas, tetapi semakin sempit pula daftar tipe aktual yang sah. Tabel berikut merangkum bentuk yang sering digunakan beserta jaminannya.

Bentuk tipe formalJaminan di dalam badan generikContoh tipe aktual
type T is privatepenugasan, salinan, dan kesamaanInteger, record apa pun
type T is limited privatetanpa penugasan, untuk tipe limitedtipe dengan sumber daya eksternal
type T is range <>operator bilangan bulat dan atribut rentangInteger dan tipe range
type T is mod <>operator bilangan bulat tak bertandaAda.Containers.Hash_Type
type T is digits <>operator titik mengambangFloat
type T is (<> )tipe diskrit beserta atributnyatipe diskrit apa pun

Bentuk is limited private menjamin lebih sedikit operasi daripada is private, yaitu penugasan antarobjek dihilangkan, sehingga tipe limited juga dapat menjadi tipe aktualnya. Bentuk is range <> dan is mod <> menjamin seluruh operator aritmetika bilangan bulat, sedangkan is digits <> menjamin aritmetika titik mengambang seperti yang digunakan pada contoh rata-rata suhu. Karena itu, pemilihan kendala merupakan keputusan rancangan: kendala ditulis seketat kebutuhan operasi di dalam badan generik.

Kendala is (<> ) sering membingungkan karena notasi (<> ) tidak menyebut kendala apa pun secara eksplisit. Notasi (<> ) berarti tipe diskrit apa pun diterima tanpa kendala tambahan, sehingga badan generik dapat menulis perulangan for Hari in T'Range atau menggunakan atribut enumerasi tanpa mengetahui nama tipe aktualnya. Bentuk is range <> mencakup seluruh tipe bilangan bulat bertanda, sedangkan is mod <> membatasi pada tipe modular yang aritmetikanya melingkar.

Parameter formal subprogram#

Parameter formal subprogram dinyatakan dengan kata with function atau with procedure, lalu diisi dengan subprogram nyata saat instansiasi. Bentuk inilah yang mengatasi kesalahan operator pada tipe formal is private, yaitu operasi yang tidak dijamin kendala tetap dapat digunakan selama disuntikkan sebagai parameter. Program berikut mengurutkan array suhu dengan prosedur generik yang kriteria urutannya disuntikkan melalui parameter formal subprogram.

ada uji_urutkan.adb
with Ada.Text_IO;
with Ada.Float_Text_IO;

procedure Uji_Urutkan is

   type Larik_Suhu is array (Positive range <>) of Float;

   --  Parameter formal subprogram: kriteria urutan disuntikkan.
   generic
      type T is private;
      type Larik is array (Positive range <>) of T;
      with function Lebih_Dulu (Kiri, Kanan : T) return Boolean;
   procedure Urutkan (Daftar : in out Larik);

   procedure Urutkan (Daftar : in out Larik) is
      Sementara : T;
   begin
      for I in Daftar'Range loop
         for J in I + 1 .. Daftar'Last loop
            if Lebih_Dulu (Daftar (J), Daftar (I)) then
               Sementara := Daftar (I);
               Daftar (I) := Daftar (J);
               Daftar (J) := Sementara;
            end if;
         end loop;
      end loop;
   end Urutkan;

   procedure Urutkan_Naik is new Urutkan
     (T => Float, Larik => Larik_Suhu, Lebih_Dulu => "<");

   procedure Urutkan_Turun is new Urutkan
     (T => Float, Larik => Larik_Suhu, Lebih_Dulu => ">");

   procedure Cetak (Judul : String; Daftar : Larik_Suhu) is
   begin
      Ada.Text_IO.Put (Judul & " :");
      for Nilai of Daftar loop
         Ada.Text_IO.Put (" ");
         Ada.Float_Text_IO.Put (Nilai, Fore => 1, Aft => 2, Exp => 0);
      end loop;
      Ada.Text_IO.New_Line;
   end Cetak;

   Suhu : Larik_Suhu := (22.5, 21.5, 23.5, 22.0);

begin
   Urutkan_Naik (Suhu);
   Cetak ("Urutan naik", Suhu);

   Suhu := (22.5, 21.5, 23.5, 22.0);
   Urutkan_Turun (Suhu);
   Cetak ("Urutan turun", Suhu);
end Uji_Urutkan;
bash
# kompilasi program
gnatmake -q uji_urutkan.adb
# jalankan program
./uji_urutkan
text Keluaran
Urutan naik : 21.50 22.00 22.50 23.50
Urutan turun : 23.50 22.50 22.00 21.50

Keluaran memperlihatkan dua urutan dari satu badan prosedur yang sama, yaitu naik melalui operator < dan turun melalui operator >. Asosiasi Lebih_Dulu => "<" menunjukkan bahwa operator juga dapat menjadi aktual untuk parameter formal subprogram, sepanjang tanda tangannya (signature) cocok. Parameter formal subprogram boleh diberi nilai bawaan dengan bentuk is <>, sehingga instansiasi boleh mengabaikannya apabila subprogram bernama sama sudah terlihat di tempat instansiasi. Pola ini digunakan secara luas pada library standar, misalnya untuk memasok fungsi hash pada container.

Kesesuaian tanda tangan menjadi syarat mutlak pada parameter formal subprogram, yaitu tipe parameter, mode, dan tipe kembalian harus cocok dengan deklarasi formalnya. Aktual berupa operator seperti < diperiksa dengan aturan yang sama, sehingga operator yang tipe operannya berbeda akan ditolak. Aturan ini menjaga keamanan tipe subprogram generik, karena seluruh operasi yang disuntikkan telah diperiksa tipenya pada waktu kompilasi.

Parameter formal package#

Parameter formal package dinyatakan dengan with package beserta pola instansiasi yang menjadi acuan package aktual. Mekanisme ini menyuntikkan seluruh isi package aktual ke dalam unit generik, sehingga generik dapat membangun di atas package lain tanpa mengetahui tipe yang digunakan instansiasi tersebut. Pola (<> ) pada posisi parameter instansiasi berarti instansiasi apa pun diterima.

ada Contoh: parameter formal package
-- tidak-dijalankan
generic
   with package Sekumpulan is new Ada.Containers.Vectors (<>);
package Analisis_Vector is
   function Rata_Rata (V : Sekumpulan.Vector) return Float;
end Analisis_Vector;

Pada kerangka di atas, package Analisis_Vector menerima instansiasi Ada.Containers.Vectors apa pun sebagai aktualnya, kemudian menggunakan tipe Vector dari instansiasi itu pada spesifikasinya. Bentuk semacam ini menghindari penulisan ulang parameter formal yang panjang, karena seluruh parameter instansiasi diwariskan sekaligus melalui package formalnya. Klien cukup menginstansiasi Analisis_Vector dengan instansiasi vector yang sudah ada, dan kedua package itu tetap konsisten karena polanya sama.

Apabila parameter instansiasi perlu dikendalikan, pola (<> ) dapat diganti dengan daftar parameter yang menyebut bagian yang wajib cocok. Bentuk daftar semacam ini menjaga konsistensi antarunit, misalnya memastikan seluruh analisis menggunakan vector dengan tipe indeks yang sama. Sisanya tetap bebas diisi oleh setiap instansiasi, sehingga kendali dan keluwesan dapat diseimbangkan.

Kesalahan umum#

Kesalahan instansiasi yang sering terjadi adalah memberikan tipe aktual yang tidak memenuhi kendala parameter formalnya. Contoh berikut menginstansiasi tipe formal is range <>, yang hanya menerima bilangan bulat bertanda, dengan tipe Float.

ada instansiasi_float_error.adb
--  Berkas ini sengaja salah: menginstansiasi tipe formal range dengan Float.
procedure Instansiasi_Float_Error is

   generic
      type T is range <>;
   function Ganda (Nilai : T) return T;

   function Ganda (Nilai : T) return T is
   begin
      return Nilai * 2;
   end Ganda;

   function Ganda_Float is new Ganda (T => Float);
begin
   null;
end Instansiasi_Float_Error;
bash
# kompilasi berkas yang menginstansiasi tipe formal range dengan Float
gnatmake -q instansiasi_float_error.adb
text Keluaran
instansiasi_float_error.adb:13:44: error: expect signed integer type in instantiation of "T"
instansiasi_float_error.adb:13:44: error: instantiation abandoned
gnatmake: "instansiasi_float_error.adb" compilation error

Pesan error menyatakan bahwa tipe aktual yang diharapkan adalah bilangan bulat bertanda (signed integer), sebab kendala is range <> menjamin aritmetika bilangan bulat di dalam badan generik. Perbaikannya adalah mengganti tipe aktual menjadi tipe bilangan bulat, misalnya Integer, atau melonggarkan kendala menjadi is digits <> apabila tipe titik mengambang memang dikehendaki. Kesalahan serupa muncul pula apabila parameter formal subprogram tanpa nilai bawaan tidak diberi aktual saat instansiasi, sehingga setiap parameter formal wajib diperiksa sebelum unit generik diinstansiasi.

Ringkasan#

  • Tipe formal berkendala menjamin operasi minimal di dalam badan generik, dan kendala yang lebih ketat menerima lebih sedikit tipe aktual.
  • Parameter formal subprogram dengan with function menyuntikkan operasi seperti operator perbandingan pada saat instansiasi.
  • Parameter formal package dengan with package ... is new ... (<> ) menyuntikkan seluruh isi instansiasi package lain tanpa menyebut tipe aktualnya.

Referensi#