1. Pengenalan Rust
Rust adalah bahasa pemrograman modern yang dikembangkan oleh Mozilla Research dan pertama kali dirilis secara stabil pada tahun 2015. Rust dirancang untuk memberikan keamanan memori (memory safety) tanpa garbage collector, sekaligus menawarkan performa yang sebanding dengan C dan C++.
Rust telah menjadi bahasa yang sangat populer dan secara konsisten dinobatkan sebagai "Bahasa Paling Dicintai" dalam survei Stack Overflow Developer Survey selama bertahun-tahun. Rust digunakan oleh perusahaan besar seperti Mozilla, Google, Microsoft, Amazon, dan Discord.
Mengapa Memilih Rust?
| Keunggulan | Penjelasan |
|---|---|
| Keamanan Memori | Ownership system mencegah bug memori seperti buffer overflow dan use-after-free saat compile time |
| Performa Tinggi | Zero-cost abstractions β tidak ada overhead runtime, secepat C/C++ |
| Concurrency Aman | Ownership system mencegah data race secara otomatis |
| Modern Tooling | Cargo (package manager) yang powerful, built-in testing, dokumentasi |
| Cross-Platform | Kompilasi untuk Windows, macOS, Linux, WebAssembly, dan embedded |
| Ekosistem Kaya | crates.io menyediakan ribuan library siap pakai |
Rust vs Bahasa Lain
| Aspek | Rust | C++ | Go |
|---|---|---|---|
| Memory Safety | π’ Compile-time | π΄ Manual | π’ Garbage Collector |
| Kecepatan | π’ Sangat Cepat | π’ Sangat Cepat | π‘ Cepat |
| Concurrency | π’ Fearless | π‘ Manual | π’ Goroutines |
| Learning Curve | π΄ Curam | π΄ Curam | π’ Mudah |
| Cocok untuk | Sistem, Web, CLI | Game, Sistem | Cloud, Microservices |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β EKOSISTEM RUST β β β β ββββββββββββ ββββββββββββ ββββββββββββββββββββ β β β Web Dev β β CLI Toolsβ β Sistem & β β β β Actix β β Clap β β Embedded β β β β Rocket β β Serde β β OS Kernel β β β β Axum β β Tokio β β Driver β β β ββββββββββββ ββββββββββββ ββββββββββββββββββββ β β β β ββββββββββββ ββββββββββββ ββββββββββββββββββββ β β β WebAssemblyβ β Game Dev β β Blockchain β β β β wasm-pack β β Bevy β β Solana β β β β Yew β β Amethyst β β Polkadot β β β ββββββββββββ ββββββββββββ ββββββββββββββββββββ β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
2. Instalasi Rust
Rust menggunakan tool bernama rustup untuk menginstal dan mengelola berbagai versi Rust. Rustup juga menginstal Cargo, package manager bawaan Rust.
Instalasi di Linux dan macOS
# Instal Rust menggunakan rustup curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Ikuti instruksi di layar, pilih opsi 1 (default installation) # Muat ulang environment source $HOME/.cargo/env # Verifikasi instalasi rustc --version # Output: rustc 1.78.0 (9b00956e5 2024-04-29) cargo --version # Output: cargo 1.78.0 (54d8815d0 2024-03-26)
Instalasi di Windows
# 1. Download rustup-init.exe dari https://rustup.rs # 2. Jalankan rustup-init.exe # 3. Ikuti instruksi instalasi (pilih opsi 1) # 4. Pastikan Visual Studio C++ Build Tools terinstal # Verifikasi di Command Prompt atau PowerShell: rustc --version # Output: rustc 1.78.0 (9b00956e5 2024-04-29) cargo --version # Output: cargo 1.78.0 (54d8815d0 2024-03-26) # Update Rust ke versi terbaru: rustup update
Menulis Program Rust Pertama
// File: hello.rs
fn main() {
println!("Halo, dunia!");
println!("Selamat datang di Rust!");
println!("Nama saya: BeebaneLabs");
}
// Kompilasi dan jalankan dari terminal:
// rustc hello.rs
// ./hello
//
// Output:
// Halo, dunia!
// Selamat datang di Rust!
// Nama saya: BeebaneLabs
Menggunakan Cargo (Package Manager)
# Buat proyek baru dengan Cargo cargo new hello_rust cd hello_rust # Struktur proyek yang dihasilkan: # hello_rust/ # βββ Cargo.toml (konfigurasi proyek) # βββ src/ # βββ main.rs (kode utama) # Kompilasi dan jalankan cargo run # Hanya kompile tanpa menjalankan cargo build # Kompilasi dengan optimasi (release mode) cargo build --release # Cek apakah kode bisa dikompile tanpa error cargo check # Jalankan unit test cargo test # Generate dan buka dokumentasi cargo doc --open
Cargo.toml β Konfigurasi Proyek
[package]
name = "hello_rust"
version = "0.1.0"
edition = "2021"
[dependencies]
# Tambahkan library dari crates.io di sini
# contoh: serde = "1.0"
# contoh: tokio = { version = "1", features = ["full"] }
Selalu gunakan Cargo untuk mengelola proyek Rust, bukan langsung menggunakan rustc. Cargo menangani kompilasi, dependency management, testing, dan banyak lagi. IDE yang direkomendasikan adalah VS Code dengan ekstensi rust-analyzer.
3. Variabel dan Tipe Data
Di Rust, variabel bersifat immutable (tidak bisa diubah) secara default. Ini adalah salah satu fitur unik Rust yang membantu mencegah bug. Anda harus menggunakan kata kunci mut secara eksplisit jika ingin mengubah nilai variabel.
Mendeklarasikan Variabel
fn main() {
// Variabel immutable (default, tidak bisa diubah)
let nama = "Budi Santoso";
let umur = 25;
println!("Nama: {}, Umur: {}", nama, umur);
// Variabel mutable (bisa diubah nilainya)
let mut skor = 100;
println!("Skor awal: {}", skor); // 100
skor = 150;
println!("Skor baru: {}", skor); // 150
// Shadowing β mendeklarasi ulang variabel dengan nama sama
let x = 5;
let x = x + 1; // x sekarang = 6
let x = x * 2; // x sekarang = 12
println!("x = {}", x); // 12
// Shadowing bisa mengubah tipe data
let angka = "42"; // string
let angka: i32 = angka.parse().unwrap(); // integer
println!("angka = {}", angka); // 42
// Deklarasi dengan tipe eksplisit
let tinggi: f64 = 175.5;
let aktif: bool = true;
let huruf: char = 'R';
println!("Tinggi: {}, Aktif: {}, Huruf: {}", tinggi, aktif, huruf);
// Konstanta β selalu immutable, harus tipe eksplisit
const PI: f64 = 3.14159265358979;
const MAKS_PESERTA: u32 = 100;
println!("PI = {}, Maks peserta = {}", PI, MAKS_PESERTA);
}
Tipe Data Dasar
| Kategori | Tipe | Contoh | Penjelasan |
|---|---|---|---|
| Integer | i8, i16, i32, i64, i128 | 42, -10 | Bilangan bulat (signed) |
| Integer | u8, u16, u32, u64, u128 | 0, 255 | Bilangan bulat (unsigned) |
| Float | f32, f64 | 3.14, -0.5 | Bilangan desimal |
| Boolean | bool | true, false | Logika benar-salah |
| Character | char | 'A', 'π¦' | Karakter Unicode (4 byte) |
| String | &str, String | "hello" | Teks (string slice dan owned) |
| Tuple | (T1, T2, ...) | (1, "hi", true) | Kumpulan tipe berbeda |
| Array | [T; N] | [1, 2, 3] | Kumpulan tipe sama, tetap ukuran |
String vs &str
fn main() {
// &str β string slice (immutable reference, fixed size)
let s1: &str = "Hello, Rust!";
// String β owned, bisa dimodifikasi
let mut s2: String = String::from("Hello");
s2.push_str(", World!");
println!("{}", s2); // Hello, World!
// Konversi &str β String
let s3: String = "hello".to_string();
let s4: String = String::from("hello");
// Konversi String β &str (dereference)
let s5: &str = &s3;
let s6: &str = s3.as_str();
// Format string
let nama = "Budi";
let umur = 25;
let pesan = format!("Nama: {}, Umur: {}", nama, umur);
println!("{}", pesan);
// Multi-line string
let teks = "\
Baris pertama
Baris kedua
Baris ketiga";
println!("{}", teks);
}
Tuple dan Array
fn main() {
// Tuple β kumpulan nilai dengan tipe berbeda
let data: (i32, f64, &str) = (42, 3.14, "Rust");
println!("Integer: {}, Float: {}, String: {}", data.0, data.1, data.2);
// Destructuring tuple
let (angka, desimal, teks) = data;
println!("angka={}, desimal={}, teks={}", angka, desimal, teks);
// Array β kumpulan nilai dengan tipe sama, ukuran tetap
let angka = [1, 2, 3, 4, 5];
println!("Elemen pertama: {}", angka[0]); // 1
println!("Elemen terakhir: {}", angka[4]); // 5
// Array dengan inisialisasi
let nol = [0; 5]; // [0, 0, 0, 0, 0]
println!("Array nol: {:?}", nol);
// Panjang array
println!("Panjang: {}", angka.len()); // 5
// Iterasi array
for item in angka.iter() {
print!("{} ", item);
}
println!();
}
4. Fungsi dan Kontrol Alur
Fungsi di Rust didefinisikan dengan kata kunci fn. Rust memiliki aturan yang ketat tentang tipe data β semua parameter dan return value harus dideklarasikan secara eksplisit.
Mendefinisikan Fungsi
// Fungsi tanpa return value
fn sapa(nama: &str) {
println!("Halo, {}! Selamat datang di Rust!", nama);
}
// Fungsi dengan return value (ekspresi terakhir tanpa semikolon)
fn tambah(a: i32, b: i32) -> i32 {
a + b // tanpa semikolon = return value
}
// Fungsi dengan return eksplisit
fn kali(a: i32, b: i32) -> i32 {
return a * b; // return eksplisit (kurang idiomatic)
}
// Fungsi dengan multiple return (menggunakan tuple)
fn bagi(a: f64, b: f64) -> (f64, f64) {
let hasil = a / b;
let sisa = a % b;
(hasil, sisa)
}
fn main() {
sapa("Budi");
let hasil = tambah(10, 20);
println!("10 + 20 = {}", hasil);
let hasil_kali = kali(5, 6);
println!("5 Γ 6 = {}", hasil_kali);
let (hasil_bagi, sisa) = bagi(17.0, 5.0);
println!("17 / 5 = {} sisa {}", hasil_bagi, sisa);
}
Kontrol Alur: if-else dan match
fn main() {
// if-else
let umur = 20;
if umur >= 17 {
println!("Dewasa");
} else if umur >= 13 {
println!("Remaja");
} else {
println!("Anak-anak");
}
// if sebagai ekspresi (bisa menghasilkan nilai)
let status = if umur >= 18 { "Dewasa" } else { "Belum dewasa" };
println!("Status: {}", status);
// match β pattern matching (switch yang powerful)
let hari = 3;
let nama_hari = match hari {
1 => "Senin",
2 => "Selasa",
3 => "Rabu",
4 => "Kamis",
5 => "Jumat",
6 => "Sabtu",
7 => "Minggu",
_ => "Tidak valid", // _ menangkap semua kemungkinan lain
};
println!("Hari ke-{} adalah {}", hari, nama_hari);
// match dengan range
let nilai = 85;
let grade = match nilai {
90..=100 => "A",
80..=89 => "B",
70..=79 => "C",
60..=69 => "D",
_ => "E",
};
println!("Nilai {} β Grade {}", nilai, grade);
}
Loop dan Iterasi
fn main() {
// loop β infinite loop
let mut counter = 0;
let hasil = loop {
counter += 1;
if counter == 5 {
break counter * 2; // break bisa mengembalikan nilai
}
};
println!("Hasil loop: {}", hasil); // 10
// while loop
let mut angka = 5;
while angka > 0 {
print!("{}... ", angka);
angka -= 1;
}
println!("Liftoff! π");
// for loop (paling sering digunakan)
for i in 1..=5 {
print!("{} ", i);
}
println!(); // 1 2 3 4 5
// Iterasi dengan enumerate
let buah = ["apel", "mangga", "jeruk"];
for (index, item) in buah.iter().enumerate() {
println!("{}. {}", index + 1, item);
}
// Iterasi collection
let angka = vec![10, 20, 30, 40, 50];
let total: i32 = angka.iter().sum();
println!("Total: {}", total); // 150
}
5. Ownership
Ownership adalah fitur paling unik dan penting di Rust. Sistem ownership memastikan keamanan memori tanpa memerlukan garbage collector. Setiap nilai di Rust memiliki satu owner (pemilik), dan ketika owner keluar dari scope, nilai tersebut otomatis di-drop (dihapus dari memori).
Tiga Aturan Ownership
- Setiap nilai di Rust memiliki tepat satu owner
- Hanya bisa ada satu owner pada satu waktu
- Ketika owner keluar dari scope, nilai di-drop secara otomatis
fn main() {
// String di-allocate di heap, s1 adalah owner
let s1 = String::from("Hello");
// MOVE: ownership dipindahkan dari s1 ke s2
let s2 = s1;
// println!("{}", s1); // ERROR! s1 sudah tidak valid
println!("s2 = {}", s2); // OK, s2 adalah owner baru
// CLONE: membuat deep copy (keduanya valid)
let s3 = s2.clone();
println!("s2 = {}, s3 = {}", s2, s3); // Keduanya valid
// Tipe data yang disimpan di stack (Copy trait) tidak berpindah
let x = 5;
let y = x; // COPY, bukan move
println!("x = {}, y = {}", x, y); // Keduanya valid!
// Ownership dan fungsi
let nama = String::from("Budi");
cetak_nama(nama); // ownership dipindahkan ke fungsi
// println!("{}", nama); // ERROR! nama sudah tidak valid
// Fungsi yang mengembalikan ownership
let nama2 = String::from("Ani");
let nama2 = ambil_dan_kembalikan(nama2);
println!("Nama2: {}", nama2); // OK, ownership dikembalikan
}
fn cetak_nama(nama: String) {
println!("Nama: {}", nama);
} // nama di-drop di sini
fn ambil_dan_kembalikan(nama: String) -> String {
println!("Memproses: {}", nama);
nama // kembalikan ownership
}
6. Borrowing dan References
Alih-alih memindahkan ownership setiap kali, kita bisa meminjam (borrow) nilai menggunakan references. Ini memungkinkan Anda mengakses data tanpa mengambil ownership-nya.
Immutable References (&T)
// Fungsi yang meminjam string (tidak mengambil ownership)
fn hitung_panjang(s: &str) -> usize {
s.len()
} // s di-drop di sini, tapi ownership tetap di pemanggil
fn main() {
let s = String::from("Hello, Rust!");
// &s membuat reference ke s, ownership TIDAK berpindah
let panjang = hitung_panjang(&s);
println!("\"{}\" panjangnya {} karakter", s, panjang); // OK!
// Multiple immutable references β diizinkan!
let r1 = &s;
let r2 = &s;
println!("r1={}, r2={}", r1, r2); // OK
}
Mutable References (&mut T)
fn tambah_excl(s: &mut String) {
s.push_str("!");
}
fn main() {
let mut pesan = String::from("Halo");
// Mutable reference β bisa mengubah data asli
tambah_excl(&mut pesan);
println!("{}", pesan); // Halo!
// Aturan: hanya SATU mutable reference pada satu waktu
let r1 = &mut pesan;
// let r2 = &mut pesan; // ERROR! Tidak bisa dua mutable ref
r1.push_str(" Dunia");
println!("{}", r1); // Halo! Dunia
// Tidak bisa gabungkan mutable dan immutable reference
// pada scope yang sama
let mut data = String::from("test");
let r_immut = &data;
// let r_mut = &mut data; // ERROR!
println!("{}", r_immut);
// Setelah r_immut selesai digunakan, baru bisa mutable:
let r_mut = &mut data;
r_mut.push_str(" ok");
println!("{}", r_mut);
}
Pada satu waktu, Anda bisa memiliki: satu mutable reference ATAU banyak immutable references, tapi tidak keduanya sekaligus. Referensi harus selalu valid (tidak boleh dangling reference).
7. Struct
Struct adalah tipe data kustom yang memungkinkan Anda mengelompokkan data terkait ke dalam satu kesatuan. Struct mirip dengan class di bahasa OOP, tetapi tanpa inheritance.
Mendefinisikan dan Menggunakan Struct
// Mendefinisikan struct
struct Mahasiswa {
nama: String,
umur: u32,
ipk: f64,
aktif: bool,
}
// Struct dengan method (implementasi)
impl Mahasiswa {
// Constructor (associated function)
fn baru(nama: &str, umur: u32) -> Self {
Mahasiswa {
nama: String::from(nama),
umur,
ipk: 0.0,
aktif: true,
}
}
// Method (mengambil &self)
fn tampilkan(&self) {
println!("{} ({} tahun, IPK: {:.2})", self.nama, self.umur, self.ipk);
}
// Method mutable (mengambil &mut self)
fn tambah_ipk(&mut self, nilai: f64) {
self.ipk = (self.ipk + nilai) / 2.0;
}
// Method yang mengambil ownership (jarang digunakan)
fn lulus(self) -> String {
format!("{} telah lulus!", self.nama)
}
}
fn main() {
// Membuat instance struct
let mhs1 = Mahasiswa {
nama: String::from("Budi"),
umur: 21,
ipk: 3.75,
aktif: true,
};
println!("Nama: {}", mhs1.nama);
println!("Umur: {}", mhs1.umur);
// Mutable struct
let mut mhs2 = Mahasiswa::baru("Ani", 20);
mhs2.tambah_ipk(3.5);
mhs2.tampilkan();
// Struct update syntax
let mhs3 = Mahasiswa {
nama: String::from("Citra"),
ipk: 3.90,
..mhs2 // sisanya dari mhs2
};
mhs3.tampilkan();
// Tuple struct
struct Warna(u8, u8, u8);
let merah = Warna(255, 0, 0);
println!("Warna: ({}, {}, {})", merah.0, merah.1, merah.2);
// Unit struct
struct Marker;
}
8. Enum dan Pattern Matching
Enum (enumeration) memungkinkan Anda mendefinisikan tipe yang bisa memiliki salah satu dari beberapa kemungkinan variant. Enum di Rust sangat powerful karena setiap variant bisa menyimpan data.
Mendefinisikan Enum
// Enum sederhana
enum Arah {
Utara,
Selatan,
Timur,
Barat,
}
// Enum dengan data
enum Pesan {
Keluar, // tanpa data
Teks(String), // satu String
Pindah { x: i32, y: i32 }, // named fields
Warna(u8, u8, u8), // tuple fields
}
// Enum dengan method
impl Pesan {
fn proses(&self) {
match self {
Pesan::Keluar => println!("Keluar dari aplikasi"),
Pesan::Teks(teks) => println!("Pesan: {}", teks),
Pesan::Pindah { x, y } => println!("Pindah ke ({}, {})", x, y),
Pesan::Warna(r, g, b) => println!("Warna: #{:02X}{:02X}{:02X}", r, g, b),
}
}
}
fn main() {
let arah = Arah::Utara;
match arah {
Arah::Utara => println!("Ke Utara β¬"),
Arah::Selatan => println!("Ke Selatan β¬"),
Arah::Timur => println!("Ke Timur β‘"),
Arah::Barat => println!("Ke Barat β¬
"),
}
// Menggunakan enum dengan data
let msg1 = Pesan::Teks(String::from("Halo Dunia"));
let msg2 = Pesan::Pindah { x: 10, y: 20 };
let msg3 = Pesan::Warna(255, 128, 0);
msg1.proses(); // Pesan: Halo Dunia
msg2.proses(); // Pindah ke (10, 20)
msg3.proses(); // Warna: FF8000
}
Option<T> β Nullable Values
// Option sudah built-in di Rust:
// enum Option<T> {
// Some(T),
// None,
// }
fn cari_index(data: &[i32], target: i32) -> Option<usize> {
for (i, &item) in data.iter().enumerate() {
if item == target {
return Some(i);
}
}
None
}
fn main() {
let angka = vec![10, 20, 30, 40, 50];
// Menggunakan match dengan Option
match cari_index(&angka, 30) {
Some(idx) => println!("Ditemukan di index {}", idx),
None => println!("Tidak ditemukan"),
}
// if let β shorthand untuk match satu case
if let Some(idx) = cari_index(&angka, 40) {
println!("Index 40: {}", idx);
}
// unwrap_or β nilai default jika None
let idx = cari_index(&angka, 99).unwrap_or(0);
println!("Index: {}", idx); // 0
// map β transformasi nilai di dalam Option
let hasil = cari_index(&angka, 30).map(|i| i * 10);
println!("Hasil: {:?}", hasil); // Some(200)
}
9. Collections
Rust menyediakan beberapa koleksi standar yang sangat berguna untuk menyimpan kumpulan data.
Vec<T> β Dynamic Array
fn main() {
// Membuat vector
let mut angka: Vec<i32> = Vec::new();
angka.push(10);
angka.push(20);
angka.push(30);
// Vec dengan macro
let buah = vec!["apel", "mangga", "jeruk"];
// Akses elemen
println!("Buah pertama: {}", buah[0]); // apel
// Akses aman dengan get (mengembalikan Option)
match buah.get(5) {
Some(item) => println!("Ada: {}", item),
None => println!("Index tidak valid"),
}
// Iterasi
for item in &buah {
print!("{} ", item);
}
println!();
// Iterasi mutable
let mut skor = vec![80, 90, 70];
for item in &mut skor {
*item += 5; // tambah 5 ke setiap skor
}
println!("Skor: {:?}", skor); // [85, 95, 75]
// Method berguna
println!("Panjang: {}", angka.len());
println!("Kosong? {}", angka.is_empty());
println!("Contains 20? {}", angka.contains(&20));
// Filter dan collect
let besar: Vec<&i32> = angka.iter().filter(|&&x| x > 15).collect();
println!("> 15: {:?}", besar); // [20, 30]
}
HashMap<K, V>
use std::collections::HashMap;
fn main() {
// Membuat HashMap
let mut nilai: HashMap<&str, i32> = HashMap::new();
// Insert data
nilai.insert("Matematika", 85);
nilai.insert("Fisika", 90);
nilai.insert("Kimia", 78);
// Akses data
if let Some(n) = nilai.get("Matematika") {
println!("Nilai Matematika: {}", n);
}
// Iterasi
for (mapel, n) in &nilai {
println!("{}: {}", mapel, n);
}
// Update: overwrite jika sudah ada
nilai.insert("Matematika", 95);
// Entry API: insert jika belum ada
nilai.entry("Biologi").or_insert(88);
nilai.entry("Matematika").or_insert(50); // tidak berubah
// Counter pattern
let teks = "halo halo dunia halo";
let mut hitungan: HashMap<&str, i32> = HashMap::new();
for kata in teks.split_whitespace() {
let count = hitungan.entry(kata).or_insert(0);
*count += 1;
}
println!("Hitungan kata: {:?}", hitungan);
}
10. Error Handling Dasar
Rust menangani error secara eksplisit menggunakan tipe Result<T, E> dan Option<T>, bukan dengan exception seperti bahasa lain.
use std::fs;
use std::num::ParseIntError;
// Fungsi yang bisa gagal β mengembalikan Result
fn bagi(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err(String::from("Tidak bisa bagi dengan nol!"))
} else {
Ok(a / b)
}
}
// Fungsi dengan ? operator (propagate error)
fn baca_angka_dari_file(path: &str) -> Result<i32, Box<dyn std::error::Error>> {
let konten = fs::read_to_string(path)?; // ? propagates error
let angka: i32 = konten.trim().parse()?; // ? propagates error
Ok(angka)
}
fn main() {
// Menggunakan Result dengan match
match bagi(10.0, 3.0) {
Ok(hasil) => println!("10 / 3 = {:.2}", hasil),
Err(e) => println!("Error: {}", e),
}
match bagi(10.0, 0.0) {
Ok(hasil) => println!("Hasil: {}", hasil),
Err(e) => println!("Error: {}", e),
}
// unwrap β langsung ambil nilai, panic jika Err
let hasil = bagi(10.0, 2.0).unwrap(); // OK: 5.0
// let gagal = bagi(10.0, 0.0).unwrap(); // PANIC!
// unwrap_or β nilai default
let hasil = bagi(10.0, 0.0).unwrap_or(0.0);
println!("Hasil: {}", hasil); // 0.0
// expect β panic dengan pesan custom
let hasil = bagi(10.0, 2.0).expect("Pembagian gagal");
// unwrap_or_else β fallback dengan closure
let hasil = bagi(10.0, 0.0).unwrap_or_else(|e| {
println!("Warning: {}", e);
0.0
});
println!("Hasil: {}", hasil);
}
π Quiz Pemahaman Rust Pemula
Uji pemahaman Anda tentang materi Rust di atas! Pilih jawaban yang paling tepat.
1. Apa yang terjadi saat kita melakukan let s2 = s1; untuk tipe String?
2. Berapa banyak mutable reference yang bisa ada pada satu waktu?
3. Apa fungsi kata kunci mut pada deklarasi variabel?
4. Apa output dari kode berikut?
let x = 5;
let x = x + 1;
let x = x * 2;
println!("{}", x);
let x = x + 1;
let x = x * 2;
println!("{}", x);