Fortran menata perhitungan yang berulang ke dalam prosedur (procedure), yaitu unit kode bernama yang dapat dipanggil berkali-kali dari bagian mana pun di dalam program. Bahasa ini menyediakan dua bentuk prosedur, yaitu fungsi (function) yang mengembalikan satu nilai melalui namanya dan subrutin (subroutine) yang menyerahkan hasil melalui argumennya. Topik ini membahas cara mendefinisikan keduanya, kapan masing-masing bentuk dipilih, semantik pass-by-reference (pass by reference) pada argumen, serta prosedur internal yang ditempatkan setelah pernyataan contains. Program uji di sepanjang topik dijalankan dengan gfortran, dan keluarannya ditampilkan apa adanya.
Fungsi dan hasil yang dikembalikan#
Fungsi (function) adalah prosedur yang mengembalikan tepat satu nilai dan dipanggil di dalam ekspresi, sebagaimana fungsi matematika pada umumnya. Definisinya dimulai dengan tipe hasil, kata function, nama fungsi, dan daftar argumen di dalam tanda kurung. Hasil perhitungan diberikan ke variabel yang namanya sama dengan nama fungsi sebelum eksekusi mencapai pernyataan end function. Karena nilainya dikembalikan, pemanggil dapat menempatkan fungsi langsung pada sisi kanan penugasan, di dalam ekspresi aritmetika, maupun sebagai argumen prosedur lain.
Fungsi juga dapat ditulis dengan klausa result(nama) sehingga variabel hasil memiliki nama tersendiri, terpisah dari nama fungsinya. Bentuk ini berguna ketika nama fungsi panjang, karena penugasan hasil dapat dilakukan pada variabel yang lebih ringkas tanpa mengubah nama yang dipakai pemanggil. Kedua bentuk berikut menghitung konversi suhu yang sama dari derajat Celsius ke derajat Fahrenheit.
! tidak-dijalankan
! fungsi dengan tipe hasil di depan nama
real function ke_fahrenheit(celsius)
implicit none
real :: celsius
ke_fahrenheit = celsius * 9.0 / 5.0 + 32.0
end function ke_fahrenheit
! fungsi yang sama dengan klausa result
real function suhu_f(celsius) result(fahrenheit)
implicit none
real :: celsius
fahrenheit = celsius * 9.0 / 5.0 + 32.0
end function suhu_fPernyataan implicit none diulang di dalam tubuh setiap fungsi karena aturan penentuan tipe variabel secara implisit berlaku per lingkup (scope) Fortran, bukan diwarisi dari unit yang memuatnya. Tanpa pengulangan itu, salah ketik nama variabel dapat lolos sebagai variabel baru yang dikenali secara implisit. Kedua definisi di atas adalah prosedur eksternal (external), yaitu unit yang berdiri sendiri di luar program utama, sehingga keduanya tidak dapat dijalankan tanpa adanya program utama yang memanggilnya.
Subrutin dan pemanggilan dengan call#
Subrutin (subroutine) adalah prosedur yang tidak mengembalikan nilai melalui namanya, melainkan menyerahkan hasil melalui argumen dan dipanggil dengan pernyataan call. Bentuk ini cocok untuk perhitungan yang menghasilkan lebih dari satu nilai, misalnya statistik ringkas dari sekumpulan nilai ujian. Program berikut memuat satu fungsi konversi suhu dan satu subrutin statistik. Keduanya ditempatkan setelah pernyataan contains, yaitu bentuk prosedur internal yang dibahas lebih rinci pada bagian Prosedur internal dengan contains.
program demo_prosedur
implicit none
real, parameter :: nilai(6) = [72.5, 88.0, 91.5, 65.0, 79.0, 84.5]
real :: rata_rata, terendah, tertinggi
! fungsi dipanggil langsung di dalam ekspresi cetak
print '(a, f8.2)', 'Suhu 25.0 C = ', ke_fahrenheit(25.0)
print '(a, f8.2)', 'Suhu 37.5 C = ', ke_fahrenheit(37.5)
! subrutin dipanggil dengan pernyataan call
call hitung_statistik(nilai, rata_rata, terendah, tertinggi)
print '(a, f8.2)', 'Rata-rata kelas = ', rata_rata
print '(a, f8.2)', 'Nilai terendah = ', terendah
print '(a, f8.2)', 'Nilai tertinggi = ', tertinggi
contains
! fungsi internal: menerima suhu Celsius dan mengembalikan Fahrenheit
real function ke_fahrenheit(celsius)
implicit none
real :: celsius
ke_fahrenheit = celsius * 9.0 / 5.0 + 32.0
end function ke_fahrenheit
! subrutin internal: mengisi tiga argumen hasil sekaligus
subroutine hitung_statistik(daftar, rata2, terendah, tertinggi)
implicit none
real :: daftar(:)
real :: rata2, terendah, tertinggi
integer :: i
rata2 = sum(daftar) / size(daftar)
terendah = daftar(1)
tertinggi = daftar(1)
do i = 2, size(daftar)
if (daftar(i) < terendah) terendah = daftar(i)
if (daftar(i) > tertinggi) tertinggi = daftar(i)
end do
end subroutine hitung_statistik
end program demo_prosedurArgumen yang dideklarasikan pada kepala prosedur disebut argumen dummy (dummy argument), sedangkan nilai yang dikirim pemanggil disebut argumen aktual (actual argument). Pada subrutin hitung_statistik, argumen dummy daftar(:) berbentuk diasumsikan (assumed shape), yaitu bentuk yang ukurannya menyesuaikan array aktual saat runtime, yakni saat program berjalan. Array (array) adalah kumpulan nilai berindeks dan menjadi struktur data utama Fortran, sehingga prosedur yang menerima array merupakan hal yang lazim pada kode numerik. Bentuk diasumsikan semacam ini menuntut antarmuka eksplisit (explicit interface), yaitu keadaan ketika compiler, program yang menerjemahkan kode sumber menjadi program mesin, mengenali seluruh ciri prosedur pada titik pemanggilannya. Syarat itu otomatis terpenuhi pada contoh ini karena prosedurnya internal, sehingga tidak ada deklarasi antarmuka tambahan yang perlu ditulis.
# mengompilasi program statistik
gfortran statistik.f90 -o statistik
# menjalankan hasil kompilasi
./statistikSuhu 25.0 C = 77.00
Suhu 37.5 C = 99.50
Rata-rata kelas = 80.08
Nilai terendah = 65.00
Nilai tertinggi = 91.50Semantik pass-by-reference#
Secara bawaan, Fortran meneruskan argumen dengan semantik pass-by-reference (pass by reference), yaitu argumen dummy menunjuk ke lokasi memori yang sama dengan argumen aktualnya. Akibatnya, penugasan pada argumen dummy langsung mengubah variabel asli di pemanggil tanpa pernyataan pengembalian apa pun. Program berikut menaikkan satu variabel suhu melalui subrutin, lalu mencetak nilainya sebelum dan sesudah pemanggilan.
program rujukan
implicit none
real :: suhu
suhu = 20.0
print '(a, f6.1)', 'Sebelum dipanggil: ', suhu
call naikkan(suhu, 5.5)
print '(a, f6.1)', 'Sesudah dipanggil: ', suhu
contains
! argumen dummy derajat menunjuk ke argumen aktual suhu
subroutine naikkan(derajat, tambahan)
implicit none
real :: derajat, tambahan
derajat = derajat + tambahan
end subroutine naikkan
end program rujukan# mengompilasi program rujukan
gfortran rujukan.f90 -o rujukan
# menjalankan hasil kompilasi
./rujukanSebelum dipanggil: 20.0
Sesudah dipanggil: 25.5Keluaran menunjukkan nilai suhu berubah dari 20.0 menjadi 25.5, meskipun program utama tidak memuat penugasan apa pun pada suhu. Perubahan itu terjadi karena derajat dan suhu menunjuk ke alamat memori yang sama selama prosedur berjalan, sehingga penugasan pada derajat di dalam naikkan pada dasarnya adalah penugasan pada suhu itu sendiri. Semantik ini membuat subrutin Fortran efisien untuk array besar karena datanya tidak disalin, tetapi sekaligus menuntut kehati-hatian pada argumen yang tidak boleh berubah.
Prosedur internal dengan contains#
Kedua program di atas menempatkan prosedurnya setelah pernyataan contains di akhir unit program. Prosedur semacam itu disebut prosedur internal dan hanya dapat dipanggil dari dalam host-nya, yaitu program yang memuatnya. Hubungan ini membentuk asosiasi host (host association), sehingga prosedur internal dapat membaca dan mengubah variabel yang dideklarasikan di host tanpa meneruskannya sebagai argumen. Prosedur internal bukan satu-satunya pilihan, karena prosedur juga dapat dikumpulkan di dalam modul bersama deklarasi dan variabel yang menyertainya.
Antarmuka prosedur internal bersifat eksplisit secara otomatis karena compiler selalu melihat definisinya bersama pemanggilnya. Dari antarmuka eksplisit itu, compiler dapat memeriksa jumlah argumen, tipe argumen, dan bentuk array pada setiap pemanggilan. Kesalahan seperti mengirim tiga argumen ke prosedur yang meminta empat langsung tertangkap saat kompilasi, bukan muncul sebagai perilaku salah yang sulit dilacak saat program berjalan. Keuntungan inilah yang menjadikan contains cara bawaan untuk menyusun program kecil hingga menengah.
Memilih antara fungsi dan subrutin#
Fungsi dan subrutin melayani kebutuhan yang berbeda, dan perbedaannya dapat diringkas ke dalam tiga aspek, yaitu nilai kembali, cara pemanggilan, dan jumlah hasil yang lazim. Tabel berikut membandingkan kedua bentuk prosedur pada ketiga aspek itu. Contoh konversi suhu dan statistik nilai ujian pada bagian-bagian sebelumnya masing-masing mewakili salah satu sisi tabel tersebut.
| Aspek | Fungsi | Subrutin |
|---|---|---|
| Nilai kembali | Satu nilai melalui nama fungsi | Tidak ada, hasil lewat argumen |
| Cara memanggil | Di dalam ekspresi | Pernyataan call |
| Jumlah hasil yang lazim | Satu | Beberapa, termasuk array |
Fungsi dipilih ketika prosedur menghasilkan satu nilai dan tidak mengubah argumennya, sehingga pemanggilannya terbaca seperti ekspresi matematika. Subrutin dipilih ketika hasilnya lebih dari satu nilai, ketika array besar perlu diperbarui di tempat, atau ketika tugasnya berupa aksi seperti membaca masukan atau mencetak laporan. Subrutin hitung_statistik pada statistik.f90 adalah contoh yang tepat karena ketiga hasilnya tidak dapat dikembalikan melalui satu nama fungsi.
Ringkasan#
- Fortran menyediakan dua bentuk prosedur, yaitu fungsi yang mengembalikan satu nilai lewat namanya dan subrutin yang menyerahkan hasil lewat argumen serta dipanggil dengan
call. - Argumen diteruskan dengan semantik pass-by-reference, sehingga penugasan pada argumen dummy langsung mengubah argumen aktualnya dan kontrak
intentdiperlukan agar compiler dapat menjaga argumen yang tidak boleh berubah. - Prosedur internal di bawah
containsmemperoleh antarmuka eksplisit secara otomatis, sehingga kesalahan jumlah, tipe, dan bentuk argumen tertangkap saat kompilasi.
Referensi#
- Learn — Fortran Programming Language — Halaman belajar resmi komunitas Fortran yang memuat tutorial quickstart dan praktik terbaik.
- The GNU Fortran Compiler — GNU Project — Manual compiler gfortran yang memuat opsi kompilasi dan karakteristik bahasa yang didukung.