Skip to content

Commit

Permalink
feat: add refcell1 exercise
Browse files Browse the repository at this point in the history
Signed-off-by: denton <denton24646@gmail.com>
  • Loading branch information
exdx committed Nov 18, 2023
1 parent 14e423f commit 749745e
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
66 changes: 66 additions & 0 deletions exercises/19_smart_pointers/refcell1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// refcell1.rs
//
// Interior mutability is a design pattern in Rust that allows you to mutate
// data even when there are immutable references to that data;
// normally, this action is disallowed by the borrowing rules.

// The RefCell<T> type represents single ownership over the data it holds.
// Recall the borrowing rules in Rust:
// 1. At any given time, you can have either (but not both) one mutable
// reference or any number of immutable references.
// 2. References must always be valid.

// With references and Box<T>, the borrowing rules’ invariants are enforced at
// compile time. With RefCell<T>, these invariants are enforced at runtime.
// With references, if you break these rules, you’ll get a compiler error.
// With RefCell<T>, if you break these rules, your program will panic and exit.
// The RefCell<T> type is useful when you’re sure your code follows the
// borrowing rules but the compiler is unable to understand and guarantee that.

// See https://doc.rust-lang.org/book/ch15-05-interior-mutability.html for more.

// I AM NOT DONE

use std::cell::RefCell;

#[derive(Debug)]
#[allow(dead_code)]
struct User {
id: u64,
name: RefCell<String>,
active: bool,
}

#[allow(dead_code)]
impl User {
fn name(&self) -> String {
self.name.borrow().to_string()
}

// Note: set_name takes an immutable reference to self but modifies the
// underlying User via the borrow_mut() RefCell API.
fn set_name(&self, name: String) {
// TODO: fix me
*self.name.borrow() = name;
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn update_name() {
let u = User {
id: 0,
name: RefCell::new("Alice".to_string()),
active: false,
};
assert_eq!(*u.name.borrow(), "Alice");

let new_name = "Bob".to_string();
u.set_name(new_name.clone());

assert_eq!(u.name.borrow().to_string(), new_name);
}
}
11 changes: 11 additions & 0 deletions info.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,17 @@ Check out https://doc.rust-lang.org/std/borrow/enum.Cow.html for documentation
on the `Cow` type.
"""

[[exercises]]
name = "refcell1"
path = "exercises/19_smart_pointers/refcell1.rs"
mode = "test"
hint = """
Remember that RefCell<T> allows for an immutable object to be modified.
Use the .borrow_mut() method on the RefCell to get a mutable reference to
the underlying data.
"""

# THREADS

[[exercises]]
Expand Down

0 comments on commit 749745e

Please sign in to comment.