CodeBlanks Logo Icon CodeBlanks

Marking done

Mark a task done by index.

Marking

To mark a task as done, we must find it by id and change its field. iter_mut().find(..) gives a &mut reference to the first matching element inside an Option:

fn tamamla(&mut self, id: u32) -> bool {
    match self.gorevler.iter_mut().find(|g| g.id == id) {
        Some(g) => {
            g.bitti = true;
            true
        }
        None => false,
    }
}

Returning false for an unknown id lets the caller show the user a message.

Shortening with if let

The same method can be written more briefly with if let:

fn tamamla(&mut self, id: u32) -> bool {
    if let Some(g) = self.gorevler.iter_mut().find(|g| g.id == id) {
        g.bitti = true;
        return true;
    }
    false
}

A similar method is used for deleting: self.gorevler.retain(|g| g.id != id); keeps the ones that don't match.

Practice Complete a task

Write the methods ekle, tamamla and listele for Liste. Add two tasks ("Süt al", "Kod yaz"); first print the results of tamamla(2) and tamamla(9) separated by a space, then show the list.

Starter code

main.rs
struct Gorev {
    id: u32,
    metin: String,
    bitti: bool,
}

struct Liste {
    gorevler: Vec<Gorev>,
    sonraki_id: u32,
}

fn main() {
    // buraya yaz
}

Sample solution

main.rs
struct Gorev {
    id: u32,
    metin: String,
    bitti: bool,
}

struct Liste {
    gorevler: Vec<Gorev>,
    sonraki_id: u32,
}

impl Liste {
    fn ekle(&mut self, metin: &str) -> u32 {
        self.sonraki_id += 1;
        self.gorevler.push(Gorev {
            id: self.sonraki_id,
            metin: metin.to_string(),
            bitti: false,
        });
        self.sonraki_id
    }
    fn tamamla(&mut self, id: u32) -> bool {
        match self.gorevler.iter_mut().find(|g| g.id == id) {
            Some(g) => {
                g.bitti = true;
                true
            }
            None => false,
        }
    }
    fn listele(&self) {
        for g in &self.gorevler {
            let isaret = if g.bitti { "x" } else { " " };
            println!("[{}] {}: {}", isaret, g.id, g.metin);
        }
    }
}

fn main() {
    let mut liste = Liste {
        gorevler: Vec::new(),
        sonraki_id: 0,
    };
    liste.ekle("Süt al");
    liste.ekle("Kod yaz");
    let a = liste.tamamla(2);
    let b = liste.tamamla(9);
    println!("{} {}", a, b);
    liste.listele();
}

Expected output

true false
[ ] 1: Süt al
[x] 2: Kod yaz

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Why didn't we use <code>self.gorevler[id as usize]</code>?

  • Indexing doesn't exist in Rust
  • It would be slower
  • u32 can't be indexed
  • Ids aren't the same as indexes (they start at 1 and shift after deletions), and a wrong id panics Correct answer

Explanation: Searching by id is both correct and safe; if nothing is found, None is returned and there's no panic.

2 Mutable search

Question
match self.gorevler.____().find(|g| g.id == id) {
    Some(g) => { g.bitti = true; true }
    None => false,
}
Answer
match self.gorevler.iter_mut().find(|g| g.id == id) {
    Some(g) => { g.bitti = true; true }
    None => false,
}

Explanation: iter_mut, which gives &mut, is needed to change the field.

3 Method and result

Term Meaning
iter_mut().find(..) Option<&mut Gorev>
retain(|g| g.id != 2) 2 is removed
tamamla(9) false
gorevler[9] Panic

All lessons in Beginner