|
1 |
| -#[cfg(test)] |
2 |
| -mod tests { |
3 |
| - #[test] |
4 |
| - fn it_works() { |
5 |
| - assert_eq!(2 + 2, 4); |
6 |
| - } |
| 1 | +// ------------------------------------- |
| 2 | +// ----------- CUSTOM MACROS ----------- |
| 3 | + |
| 4 | +#[macro_export] |
| 5 | +/// Use to take mutable ownership of _specific_ variables within a closure. |
| 6 | +/// |
| 7 | +/// Closures try to be "smart" about how much scope they capture. If you don't mutate a variable |
| 8 | +/// they take `&var`, if you do mutate they take `&mut var`. However, if you require ownership you use |
| 9 | +/// `move`, i.e. `move || {... do stuff with var...}`... _right_? |
| 10 | +/// |
| 11 | +/// The problem with `move` is that it moves _every_ variable that is referenced. If you only need |
| 12 | +/// to move _one_ variable it can be a pain. Interestingly, you can tell the compiler to only move |
| 13 | +/// _specific_ variables like so: |
| 14 | +/// |
| 15 | +/// ```no_compile |
| 16 | +/// let x = x; |
| 17 | +/// let y = y; |
| 18 | +/// // ... etc |
| 19 | +/// ``` |
| 20 | +/// |
| 21 | +/// But this is quite silly and not obvious to someone who doesn't know about it. Instead, use the |
| 22 | +/// `own!` macro and your code will be self documenting. |
| 23 | +/// |
| 24 | +/// > Note: this macro always does `let mut x = x` to mimick its primary usecase of closures |
| 25 | +/// > (which infer mutability automatically). If you require non-mutable ownership use `let x = x` |
| 26 | +/// > directly. |
| 27 | +/// |
| 28 | +/// # Examples |
| 29 | +/// ``` |
| 30 | +/// #[macro_use] extern crate std_prelude; |
| 31 | +/// |
| 32 | +/// # fn main() { |
| 33 | +/// let y = vec![1, 2, 3]; |
| 34 | +/// let mut x = vec![1, 2, 3]; |
| 35 | +/// let z = vec![10]; |
| 36 | +/// |
| 37 | +/// // create scope in which we mutate `x` |
| 38 | +/// { |
| 39 | +/// let closure = || { |
| 40 | +/// own!(y, z); |
| 41 | +/// x.push(4); // mutate reference to x |
| 42 | +/// z.push(10); |
| 43 | +/// |
| 44 | +/// println!("&x: {:?}", &x); |
| 45 | +/// println!("moved y: {:?}", y); |
| 46 | +/// println!("moved z: {:?}", z); |
| 47 | +/// }; |
| 48 | +/// |
| 49 | +/// closure(); |
| 50 | +/// } |
| 51 | +/// |
| 52 | +/// println!("&x after: {:?}", x); // We can still print x! |
| 53 | +/// // println!("y after: {:?}", y); // ERROR: use of moved value |
| 54 | +/// // println!("z after: {:?}", z); // ERROR: use of moved value |
| 55 | +/// # } |
| 56 | +/// ``` |
| 57 | +macro_rules! own { |
| 58 | + ( $( $x:ident ),* ) => { |
| 59 | + #[allow(unused_mut)] |
| 60 | + $( |
| 61 | + let mut $x = $x; |
| 62 | + )* |
| 63 | + }; |
7 | 64 | }
|
0 commit comments