zng_var/expr.rs
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
///<span data-del-macro-root></span> New variable from an expression with interpolated vars.
///
/// # Interpolation
///
/// Other variables can be interpolated by quoting the var with `#{..}`. When
/// an expression contains other interpolated vars the expression var updates when
/// any of the interpolated vars update.
///
/// # Examples
///
/// ```
/// # use zng_var::*;
/// let var_a = var(10);
/// let var_b = var(10);
/// let name = "var_eq";
/// let var_eq = expr_var! {
/// let eq = #{var_a} == #{var_b};
/// println!("{} updated: {} == {}: {}", name, #{var_a}, #{var_b}, eq);
/// eq
/// };
/// ```
///
/// In the example a `var_eq` var of type `impl Var<bool>` is created. When either `var_a` or `var_b` are set
/// the value of `var_eq` is updated. Normal variables like `name` are moved in, like a closure capture.
///
/// # Capture Mode
///
/// The expression operates like a closure that captures by `move`. Both the interpolated variables and any
/// other `let` binding referenced from the scope are moved into the resulting variable.
///
/// # Interpolation
///
/// Variable interpolation is done by quoting the variable with `#{<var-expr>}`, the braces are required.
///
/// The `<var-expr>` is evaluated before *capturing* starts so if you interpolate `#{var_a.clone()}` `var_a`
/// will still be available after the `expr_var` call. Equal `<var-expr>` only evaluate once.
///
/// # Expansion
///
/// The expression is transformed into different types of vars depending on the number of interpolated variables.
///
/// ##### No Variables
///
/// An expression with no interpolation is simply evaluated into a var using [`IntoVar`].
///
/// ##### Single Variable
///
/// An expression with a single variable is transformed in a [`map`] operation, unless the expression
/// is only the variable without any extra operation.
///
/// ##### Multiple Variables
///
/// An expression with multiple variables is transformed into a [`merge_var!`] call.
///
/// [`Var::get`]: crate::Var::get
/// [`map`]: crate::Var::map
/// [`IntoVar`]: crate::IntoVar
/// [`merge_var!`]: crate::merge_var
#[macro_export]
macro_rules! expr_var {
($($expr:tt)+) => {
$crate::types::__expr_var! { $crate, $($expr)+ }
};
}
#[doc(hidden)]
pub use zng_var_proc_macros::expr_var as __expr_var;
use super::{IntoVar, Var, VarValue};
#[doc(hidden)]
pub fn expr_var_into<T: VarValue>(expr: impl IntoVar<T>) -> impl Var<T> {
expr.into_var()
}
#[doc(hidden)]
pub fn expr_var_as<T: VarValue>(var: impl Var<T>) -> impl Var<T> {
var
}
#[doc(hidden)]
pub fn expr_var_map<I: VarValue, O: VarValue>(input: impl Var<I>, map: impl FnMut(&I) -> O + Send + 'static) -> impl Var<O> {
input.map(map)
}