RefCell<Option<T>> can model a cache that starts empty and is filled when the value is first requested.

Program

Play the program to choose a source value and store it in a small cache.

source
refcell_cache.rs
Replay: real traced execution (multi-file project)
use std::cell::RefCell;

fn main() {
    let source = "primary";
    let cache = RefCell::new(None);
    let value = cached_value(&cache, source);
    println!("{value}");
}

fn cached_value(cache: &RefCell<Option<String>>, source: &str) -> String {
    if cache.borrow().is_none() {
        *cache.borrow_mut() = Some(source.to_string());
    }
    cache.borrow().clone().unwrap()
}
use std::cell::RefCell;

fn main() {
    let source = "backup";
    let cache = RefCell::new(None);
    let value = cached_value(&cache, source);
    println!("{value}");
}

fn cached_value(cache: &RefCell<Option<String>>, source: &str) -> String {
    if cache.borrow().is_none() {
        *cache.borrow_mut() = Some(source.to_string());
    }
    cache.borrow().clone().unwrap()
}
use std::cell::RefCell;

fn main() {
    let source = "none";
    let cache = RefCell::new(None);
    let value = cached_value(&cache, source);
    println!("{value}");
}

fn cached_value(cache: &RefCell<Option<String>>, source: &str) -> String {
    if cache.borrow().is_none() {
        *cache.borrow_mut() = Some(source.to_string());
    }
    cache.borrow().clone().unwrap()
}
  1. source ← "primary", cache ← RefCell { value: None }

    3fn main() {4    let sourc→ "primary"e = "primary"; //@source="primary", "backup", "none"5    let cach→ RefCell { value: None }e = RefCell::new(None);6    let value = cached_value(&cachRefCell { value: None }e, sourc"primary"e);7    println!("{value}");
  2. cache.borrow().clone().unwrap()

    13    }14    cache.borrow().clone().unwrap()15}
  3. cache ← RefCell { value: Some("primary") }, value ← "primary"

    5    let cache = RefCell::new(None);6    let valu→ "primary"e = cached_value(&cach→ RefCell { value: Some("primary") }e, sourc"primary"e);7    println!("{value}");8}
    outputprimary
  1. source ← "backup", cache ← RefCell { value: None }

    3fn main() {4    let sourc→ "backup"e = "backup";5    let cach→ RefCell { value: None }e = RefCell::new(None);6    let value = cached_value(&cachRefCell { value: None }e, sourc"backup"e);7    println!("{value}");
  2. cache.borrow().clone().unwrap()

    13    }14    cache.borrow().clone().unwrap()15}
  3. cache ← RefCell { value: Some("backup") }, value ← "backup"

    5    let cache = RefCell::new(None);6    let valu→ "backup"e = cached_value(&cach→ RefCell { value: Some("backup") }e, sourc"backup"e);7    println!("{value}");8}
    outputbackup
  1. source ← "none", cache ← RefCell { value: None }

    3fn main() {4    let sourc→ "none"e = "none";5    let cach→ RefCell { value: None }e = RefCell::new(None);6    let value = cached_value(&cachRefCell { value: None }e, sourc"none"e);7    println!("{value}");
  2. cache.borrow().clone().unwrap()

    13    }14    cache.borrow().clone().unwrap()15}
  3. cache ← RefCell { value: Some("none") }, value ← "none"

    5    let cache = RefCell::new(None);6    let valu→ "none"e = cached_value(&cach→ RefCell { value: Some("none") }e, sourc"none"e);7    println!("{value}");8}
    outputnone
Option cache `None` means the cache is empty; `Some(value)` stores the computed data.
borrow_mut `borrow_mut` opens a checked mutable borrow for filling the cache.
clone The helper returns an owned `String` so the borrow does not escape the function.