Topik ini membahas mode parameter pada fungsi Carbon, yaitu aturan yang menentukan apakah sebuah parameter hanya dapat dibaca atau juga dapat diubah di dalam tubuh fungsi. Pembahasan mencakup parameter sebagai binding nilai secara bawaan, mutasi dengan awalan var, serta status mode let eksplisit yang ada dalam desain tetapi belum diterima interpreter Explorer. Setelah topik ini, fungsi dengan masukan yang aman dari perubahan tak disengaja dapat ditulis dan diuji di Compiler Explorer.
Parameter sebagai binding nilai#
Parameter fungsi Carbon ditulis di dalam tanda kurung dengan pola nama: tipe, dan pola tersebut pada dasarnya adalah binding yang sama dengan deklarasi let. Menurut dokumen desain, parameter bawaan berperilaku sebagai value binding, yaitu nama yang terikat pada nilai masukan, sehingga nilainya dapat dibaca tetapi tidak dapat ditimpa. Desain ini memilih nilai sebagai bawaan karena masukan merupakan peran yang paling dominan bagi parameter fungsi. Fungsi yang hanya membaca masukannya juga lebih mudah dianalisis, karena aliran data di dalamnya tidak mengandung perubahan nilai yang tak terduga.
Fungsi berikut mengonversi suhu dari skala Celsius ke Fahrenheit dan hanya membaca parameternya. Tanda panah -> menyatakan tipe kembalian, dan setiap jalur eksekusi harus diakhiri return dengan nilai yang sesuai. Nama parameter di sini sekaligus menjadi dokumentasi, karena pemanggil dapat melihat bahwa masukan adalah nilai Celsius dan hasilnya adalah nilai Fahrenheit.
// tidak-dijalankan
fn KonversiKeFahrenheit(celsius: i32) -> i32 {
return celsius * 9 / 5 + 32;
}Potongan di atas adalah fragmen, sehingga belum mencakup header package dan fungsi Main yang diperlukan agar program dapat dijalankan. Program utuh yang memuat kedua fungsi pada topik ini tersedia di bagian berikutnya.
Mutasi parameter dengan var#
Awalan var pada parameter mengubah bindingnya menjadi penyimpanan yang dapat ditimpa, sebagaimana var pada deklarasi lokal. Mode ini cocok untuk fungsi yang mengolah masukannya secara bertahap sebelum menghasilkan keluaran, misalnya menghitung nilai akhir dari sebuah ukuran setelah beberapa penyesuaian. Program berikut memuat dua fungsi, yaitu fungsi konversi yang membaca parameternya saja dan fungsi yang mengalikan parameternya dengan tiga di dalam tubuh fungsi.
package sample api;
fn KonversiKeFahrenheit(celsius: i32) -> i32 {
return celsius * 9 / 5 + 32;
}
fn Naikkan(var n: i32) -> i32 {
n = n * 3;
return n;
}
fn Main() -> i32 {
Print("100 C = {0} F", KonversiKeFahrenheit(100));
Print("Naikkan(5) = {0}", Naikkan(5));
return 0;
}100 C = 212 F
Naikkan(5) = 15
result: 0Penugasan n = n * 3; hanya sah karena n dideklarasikan dengan var n: i32 pada daftar parameter. Tanpa awalan var, baris yang sama akan ditolak sebagaimana ditunjukkan pada bagian kesalahan umum. Mutasi semacam ini terjadi pada penyimpanan milik fungsi itu sendiri, sehingga desain tidak memberi dampak apa pun kepada variabel milik pemanggil. Pola var pada parameter dengan demikian berbeda maksud dari pengiriman alamat pada C++, karena yang dimaksudkan hanyalah memperbolehkan tulis ulang secara lokal.
Mode ditetapkan per parameter, sehingga satu fungsi boleh mencampur keduanya. Program berikut menjadikan aturan sebagai masukan yang hanya dibaca dan n sebagai nilai kerja yang dikalikan di dalam tubuh fungsi.
package sample api;
fn Gabung(aturan: i32, var n: i32) -> i32 {
n = n * aturan;
return n;
}
fn Main() -> i32 {
Print("Gabung(4, 12) = {0}", Gabung(4, 12));
return 0;
}Gabung(4, 12) = 48
result: 0Daftar parameter fungsi semacam ini langsung menyatakan peran setiap masukan tanpa perlu membaca tubuh fungsinya, yaitu aturan sebagai faktor tetap dan n sebagai nilai kerja yang berubah. Pola campuran ini cocok untuk perhitungan bertahap, misalnya mengalikan sebuah nilai dengan faktor tertentu sebelum hasilnya diolah lebih lanjut oleh pemanggil. Sifatnya pun merupakan turunan langsung dari aturan binding, karena setiap parameter adalah pola binding tersendiri yang memilih mode masing-masing.
Kesalahan umum#
Kesalahan pertama adalah menimpa parameter yang dideklarasikan tanpa var. Program berikut sengaja melakukan penugasan pada parameter biasa agar pesan errornya terlihat.
package sample api;
fn TambahSatu(x: i32) -> i32 {
x = x + 1;
return x;
}
fn Main() -> i32 {
Print("{0}", TambahSatu(4));
return 0;
}COMPILATION ERROR: <source>:4: Only a reference expression can be assigned to, but got `x`Pesan errornya identik dengan error penimpaan binding let, karena parameter biasa memang memiliki semantik yang sama. Perbaikannya ada dua jalur. Apabila nilai parameter memang perlu berubah saat diolah, tambahkan awalan var pada parameternya. Apabila perhitungan hanya butuh nilai turunan, buat binding lokal baru, misalnya var hasil: i32 = x + 1;, dan biarkan parameter tetap bersih dari mutasi.
Kesalahan kedua adalah menuliskan mode let secara eksplisit pada parameter, sebuah bentuk yang tampak logis tetapi belum diterima interpreter.
package sample api;
fn Tampilkan(let x: i32) -> i32 {
return x;
}
fn Main() -> i32 {
Print("{0}", Tampilkan(4));
return 0;
}SYNTAX ERROR: <source>:3: syntax error, unexpected LETStatus yang jujur untuk bentuk ini adalah menunggu. Dokumen desain menetapkan bahwa pola parameter secara bawaan sudah berperilaku let, sedangkan penulisan kata kuncinya secara eksplisit belum didukung parser Explorer, sehingga parameter yang hanya dibaca cukup ditulis tanpa awalan apa pun. Apabila versi interpreter berikutnya menerima kata kunci tersebut, bentuk let x: i32 akan menjadi penanda pembacaan yang sejajar dengan var.
Ringkasan#
- Parameter tanpa awalan adalah binding nilai yang tidak dapat ditimpa, sejajar dengan semantik
letpada deklarasi lokal. - Awalan
varpada parameter, misalnyafn Naikkan(var n: i32), mengizinkan penugasan di dalam tubuh fungsi, dan mode boleh dicampur per parameter sepertifn Gabung(aturan: i32, var n: i32). - Penugasan pada parameter tanpa
varditolak dengan errorOnly a reference expression can be assigned to. - Kata kunci
leteksplisit pada parameter merupakan bagian desain yang masih ditolak parser Explorer dengan pesansyntax error, unexpected LET.
Referensi#
- Values, objects, and expressions — Carbon Language — Dokumen desain yang menetapkan parameter sebagai binding nilai beserta kasus parameter var yang mengonsumsi masukan.
- Functions — Carbon Language — Dokumen desain fungsi Carbon yang memuat bentuk deklarasi, pola parameter, dan pernyataan return.
- Carbon Explorer — Compiler Explorer — Layanan daring tempat seluruh program pada topik ini dijalankan dengan kompiler Explorer (trunk).