1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! Some extension functions that are convenient for side effects

/// using
/// ## Usage
/// ```rust
/// # use libsugar::*;
/// let v = (1, 2);
/// let v2 = (3, 4);
/// using!((a, b) = v, (c, d) = v2; {
///   println!("{} {} {} {}", a, b, c, d)
///   # ;
///   # assert_eq!(a, 1);
///   # assert_eq!(b, 2);
///   # assert_eq!(c, 3);
///   # assert_eq!(d, 4);
/// })
/// ```
/// *equivalent to*
/// ```no_run
/// let v = (1, 2);
/// let v2 = (3, 4);
/// {
///   let (a, b) = v;
///   let (c, d) = v2;
///   {
///     println!("{} {} {} {}", a, b, c, d)
///   }
/// }
///   ```
#[macro_export(local_inner_macros)]
macro_rules! using {
    { $($p:pat = $v:expr),* ; $b:block } => {
        { $(let $p = $v ;)* $b }
    };
}

/// Create an implicit variable, and make a mapping for it
/// ## Example
/// ```rust
/// # use libsugar::Used;
/// let v = 1.used(|v| { v + 1 });
/// assert_eq!(v, 2);
/// ```
pub trait Used: Sized {
    /// Create an implicit variable, and make a mapping for it
    /// ## Example
    /// ```rust
    /// # use libsugar::Used;
    /// let v = 1.used(|v| { v + 1 });
    /// assert_eq!(v, 2);
    /// ```
    fn used<F: FnOnce(Self) -> R, R>(self, f: F) -> R;
}
impl<T> Used for T {
    fn used<F: FnOnce(Self) -> R, R>(self, f: F) -> R {
        f(self)
    }
}

/// Create an implicit variable, do some extra thing, and return it
/// ## Example
/// ```rust
/// # use libsugar::Also;
/// let v = 1.also(|v| { println!("{}", v) });
/// assert_eq!(v, 1);
/// ```
pub trait Also: Sized {
    /// Create an implicit variable, do some extra thing, and return it
    /// ## Example
    /// ```rust
    /// # use libsugar::Also;
    /// let v = 1.also(|v| { println!("{}", v) });
    /// assert_eq!(v, 1);
    /// ```
    fn also<F: FnOnce(&Self)>(self, f: F) -> Self;
}
impl<T> Also for T {
    fn also<F: FnOnce(&Self)>(self, f: F) -> Self {
        f(&self);
        self
    }
}

/// Create an implicit variable, do some extra thing, and return it
/// ## Example
/// ```rust
/// # use libsugar::AlsoMut;
/// let v = 1.also_mut(|v| {
///     println!("{}", v);
///     *v += 1;
/// });
/// assert_eq!(v, 2);
/// ```
pub trait AlsoMut: Sized {
    /// Create an implicit variable, do some extra thing, and return it
    /// ## Example
    /// ```rust
    /// # use libsugar::AlsoMut;
    /// let v = 1.also_mut(|v| {
    ///     println!("{}", v);
    ///     *v += 1;
    /// });
    /// assert_eq!(v, 2);
    /// ```
    fn also_mut<F: FnOnce(&mut Self)>(self, f: F) -> Self;
}
impl<T> AlsoMut for T {
    fn also_mut<F: FnOnce(&mut Self)>(mut self, f: F) -> Self {
        f(&mut self);
        self
    }
}

/// Run function immediately 
#[inline(always)]
pub fn run<R>(f: impl FnOnce() -> R) -> R {
    f()
}