Memorized value if needed


#1

This just made me think I’m incredibly stupid.

I have a function that takes an object and writes a serialized version as a message to several clients, like this:

fn write_it(&self, obj: &Obj) {
    for client in &self.clients {
        // some code to determine if the client wants the message
        let wants = true; // or false
        if wants {
            client.write(obj.to_string());
        }
    }
}

Now I want to format the message (call to_string()) only once, but only if any client wants it. In other languages I would probably use a variable set initially to null, and when replace that by the stringified message when needed. In Rust this should be doable with Option, but I couldn’t find a nice way to express it. Best try was something like this:

fn write_it(&self, obj: &Obj) {
    let mut msg = None;
    for client in &self.clients {
        // some code to determine if the client wants the message
        let wants = true; // or false
        if wants {
            if msg == None {
                msg = Some(obj.to_string());
            }
            match msg {
                Some(ref str) => client.write(str),
                None => panic!("cannot happen")
            }
        }
    }
}

I have tried but failed to put everything into a single match. I can’t get the string out of the Option without matching…

Is there any better way to have a “memorized” value that is calculated only once when needed?


#2

How about this?

    let s = msg.unwrap_or_else(|| obj.to_string());
    client.write(s);
    msg = Some(s);

#3

If you really want to get fancy, you can use the lazy crate:
https://crates.io/crates/lazy


#4

Fancy! It does reassign “msg” on every loop, but I guess that’s not a big thing.


#5

Hm, the lack of a “Documentation” link on the page makes me a bit nervous about using it…


#6

The documentation is in the repo (https://github.com/reem/rust-lazy). It’s literally just a macro.


#7

OK, fair enough. The more serious issue is that it (or more correctly, its dependency oncemutex) doesn’t compile on current nightly Rust :smile: