Mode Parameter

Parameter let eksplisit untuk pembacaan dan var untuk mutasi di dalam fungsi.

Daftar isi

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.

carbon Contoh: fungsi dengan parameter yang hanya dibaca
// 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.

carbon parameter.carbon
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;
}
text Keluaran
100 C = 212 F
Naikkan(5) = 15
result: 0

Penugasan 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.

carbon gabung.carbon
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;
}
text Keluaran
Gabung(4, 12) = 48
result: 0

Daftar 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.

carbon ubah-param.carbon
package sample api;

fn TambahSatu(x: i32) -> i32 {
  x = x + 1;
  return x;
}

fn Main() -> i32 {
  Print("{0}", TambahSatu(4));
  return 0;
}
text Keluaran
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.

carbon let-param.carbon
package sample api;

fn Tampilkan(let x: i32) -> i32 {
  return x;
}

fn Main() -> i32 {
  Print("{0}", Tampilkan(4));
  return 0;
}
text Keluaran
SYNTAX ERROR: <source>:3: syntax error, unexpected LET

Status 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 let pada deklarasi lokal.
  • Awalan var pada parameter, misalnya fn Naikkan(var n: i32), mengizinkan penugasan di dalam tubuh fungsi, dan mode boleh dicampur per parameter seperti fn Gabung(aturan: i32, var n: i32).
  • Penugasan pada parameter tanpa var ditolak dengan error Only a reference expression can be assigned to.
  • Kata kunci let eksplisit pada parameter merupakan bagian desain yang masih ditolak parser Explorer dengan pesan syntax error, unexpected LET.

Referensi#