Error Propagation — Rust

Error Propagation di Rust Ketika fungsi bisa gagal, kita perlu cara untuk meneruskan error ke caller. Rust menyediakan operator ? yang membuat error propagation

Error Propagation di Rust

Ketika fungsi bisa gagal, kita perlu cara untuk meneruskan error ke caller. Rust menyediakan operator ? yang membuat error propagation menjadi sangat ergonomis.

Tanpa ? Operator (Manual)

use std::num::ParseIntError;

fn hitung_ganda(s: &str) -> Result<i32, ParseIntError> {
    let angka = match s.parse::<i32>() {
        Ok(n) => n,
        Err(e) => return Err(e),  // propagate error
    };
    Ok(angka * 2)
}

Dengan ? Operator (Idiomatic)

fn hitung_ganda(s: &str) -> Result<i32, ParseIntError> {
    let angka = s.parse::<i32>()?;  // ? = jika Err, langsung return Err
    Ok(angka * 2)
}

// Bahkan lebih singkat:
fn hitung_ganda_v2(s: &str) -> Result<i32, ParseIntError> {
    Ok(s.parse::<i32>()? * 2)
}

Chaining dengan ?

fn proses_data(input: &str) -> Result<i32, ParseIntError> {
    let step1 = input.trim().parse::<i32>()?;
    let step2 = (step1 * 2).to_string().parse::<i32>()?;
    Ok(step2 + 10)
}

Custom Error Type

use std::fmt;

#[derive(Debug)]
enum AppError {
    ParseError(String),
    ValidationError(String),
    NotFound(String),
}

impl fmt::Display for AppError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            AppError::ParseError(msg) => write!(f, "Parse error: {}", msg),
            AppError::ValidationError(msg) => write!(f, "Validation error: {}", msg),
            AppError::NotFound(msg) => write!(f, "Not found: {}", msg),
        }
    }
}

fn validasi_umur(input: &str) -> Result<u32, AppError> {
    let umur: u32 = input.parse()
        .map_err(|_| AppError::ParseError("Bukan angka".into()))?;

    if umur > 150 {
        return Err(AppError::ValidationError("Umur tidak valid".into()));
    }

    Ok(umur)
}

? dengan Option

fn first_even(v: &[i32]) -> Option<i32> {
    let first = v.first()?;  // return None jika kosong
    if first % 2 == 0 {
        Some(*first)
    } else {
        None
    }
}

Best Practices

Yang akan kamu pelajari