CodeBlanks Logo Icon CodeBlanks

Context ekleme

anyhow::Context ile hataya bağlam eklersin.

Context ekleme

"invalid digit found in string" mesajı neyin başarısız olduğunu söylemez. İyi bir hata, ne yapılırken başarısız olunduğunu anlatır. anyhow'da bunun için context ve with_context vardır:

use anyhow::{Context, Result};

fn port_oku(s: &str) -> Result<u16> {
    s.parse::<u16>()
        .with_context(|| format!("port okunamadı ({s})"))
}
// hata: port okunamadı (99999)
// Caused by: number too large to fit in target type

with_context closure aldığı için mesaj yalnızca hata durumunda üretilir.

std ile bağlam

Dış crate olmadan aynı etki map_err ile elde edilir: alt hatayı ve bağlamı tek mesajda birleştirirsin:

fn port_oku(s: &str) -> Result<u16, String> {
    s.parse::<u16>()
        .map_err(|e| format!("port okunamadı ({s}): {e}"))
}

println!("{:?}", port_oku("8080"));   // Ok(8080)

Bu yöntem alt hatayı metne çevirir; zinciri korumak için bir sonraki derste source() metoduna bakacağız.

Uygulama Bağlamlı hata

Yukarıdaki port_oku fonksiyonunu map_err ile yaz. "8080" sonucunu {:?} ile, "99999" hatasını ise düz metin olarak ayrı satırlara yazdır.

Başlangıç kodu

main.rs
fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
fn port_oku(s: &str) -> Result<u16, String> {
    s.parse::<u16>()
        .map_err(|e| format!("port okunamadı ({s}): {e}"))
}

fn main() {
    println!("{:?}", port_oku("8080"));
    if let Err(e) = port_oku("99999") {
        println!("{}", e);
    }
}

Beklenen çıktı

Ok(8080)
port okunamadı (99999): number too large to fit in target type

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Bağlam mesajına en çok ne eklenmelidir?

  • Satır numarası
  • Kullanıcının adı
  • Hiçbir şey; alt hata yeterli
  • Yapılan işlem ve ilgili girdi (dosya adı, anahtar, değer) Doğru cevap

Açıklama: Kullanıcı mesajdan sorunu bulabilmeli: "ayar.toml okunamadı" ile "No such file" birlikte anlam kazanır.

2 Tembel bağlam

Soru
s.parse::<u16>()
    .____(|| format!("port okunamadı ({s})"))
Cevap
s.parse::<u16>()
    .with_context(|| format!("port okunamadı ({s})"))

Açıklama: with_context mesajı yalnızca hata olduğunda üretir.

3 Girdi ve port_oku sonucu

Kavram Anlamı
"8080" Ok(8080)
"99999" number too large ...
"abc" invalid digit ...
"" cannot parse ... empty string

Orta seviye bölümündeki tüm dersler