# drop_cell An alternative way of implementing [`Drop`](https://doc.rust-lang.org/nightly/core/ops/trait.Drop.html) in Rust. ## Overview This library provides the `defer!` macro to defer execution until the end of the stack frame. The `defer!` macro emulates [Golang Defer statements](https://go.dev/ref/spec#Defer_statements). ```rust defer!(println!("world")); println!("hello"); return; println!("unreachable"); ``` Output: ```markdown hello world ```` ## Borrowing rules The following code won't compile. ```rust let mut v = vec![1, 2]; defer!(assert_eq!(v, &[1, 2, 3])); // └─ immutable borrow occurs here ──────────┐ v.push(3); // │ // └─ mutable borrow occurs here │ // │ // immutable borrow will be used at the end of the stack frame ─┘ ``` We want to run `assert_eq!(v, &[1, 2, 3])` at the end of the stack frame, but it breaks the [borrowing rules](https://doc.rust-lang.org/stable/book/ch04-02-references-and-borrowing.html#mutable-references). To work around, we need to pass `v` into `defer!`. ```rust let v = vec![1, 2]; // └─ consumes it ─┐ // ┌────────────┘ defer!(v => assert_eq!(v, &[1, 2, 3])); v.push(3); ``` ## Example ```rust use drop_cell::defer; use std::io::Write; use std::sync::mpsc; fn main() { no_arg(); args(); bind(); } fn no_arg() { let (tx, rx) = mpsc::channel(); defer! { assert_eq!(rx.recv().unwrap(), "hello"); assert_eq!(rx.recv().unwrap(), "world"); }; tx.send("hello").unwrap(); tx.send("world").unwrap(); } fn args() { let (v1, v2) = (vec![], vec![]); defer! { v1, v2 => assert_eq!(v1, b"hello"); assert_eq!(v2, b"world"); } write!(v1, "hello").unwrap(); write!(v2, "world").unwrap(); } fn bind() { let ss = vec![]; defer! { v @ Some(ss) => let v = v.take().unwrap(); assert_eq!(v.as_slice(), ["hello", "world"]); } v.as_mut().unwrap().push("hello"); v.as_mut().unwrap().push("world"); } ``` ## When and when not ###### When to use - When you want a [Finalizer](https://en.wikipedia.org/wiki/Finalizer) but reluctant to create a `struct` for it. ###### When NOT to use - When [RAII](https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization) pattern is preferable. e.g. [Lock](https://en.wikipedia.org/wiki/Lock_(computer_science)) and [Reference Counting](https://en.wikipedia.org/wiki/Reference_counting). - When the code is written inside a method, using `defer!` might complicate the code.