zng_var/var_impl/
expr_var.rs

1///<span data-del-macro-root></span> New variable from an expression with interpolated vars.
2///
3/// # Interpolation
4///
5/// Other variables can be interpolated by quoting the var with `#{..}`. When
6/// an expression contains other interpolated vars the expression var updates when
7/// any of the interpolated vars update.
8///
9/// # Examples
10///
11/// ```
12/// # use zng_var::*;
13/// let var_a = var(10);
14/// let var_b = var(10);
15/// let name = "var_eq";
16/// let var_eq = expr_var! {
17///     let eq = #{var_a} == #{var_b};
18///     println!("{} updated: {} == {}: {}", name, #{var_a}, #{var_b}, eq);
19///     eq
20/// };
21/// ```
22///
23/// In the example a `var_eq` var of type `Var<bool>` is created. When either `var_a` or `var_b` are set
24/// the value of `var_eq` is updated. Normal variables like `name` are moved in, like a closure capture.
25///
26/// # Capture Mode
27///
28/// The expression operates like a closure that captures by `move`. Both the interpolated variables and any
29/// other `let` binding referenced from the scope are moved into the resulting variable.
30///
31/// # Interpolation
32///
33/// Variable interpolation is done by quoting the variable with `#{<var-expr>}`, the braces are required.
34///
35/// The `<var-expr>` is evaluated before *capturing* starts so if you interpolate `#{var_a.clone()}` `var_a`
36/// will still be available after the `expr_var` call. Equal `<var-expr>` only evaluate once.
37///
38/// # Expansion
39///
40/// The expression is transformed into different types of vars depending on the number of interpolated variables.
41///
42/// ##### No Variables
43///
44/// An expression with no interpolation is simply evaluated into a var using [`IntoVar`].
45///
46/// ##### Single Variable
47///
48/// An expression with a single variable is transformed in a [`map`] operation, unless the expression
49/// is only the variable without any extra operation.
50///
51/// ##### Multiple Variables
52///
53/// An expression with multiple variables is transformed into a [`merge_var!`] call.
54///
55/// [`Var::get`]: crate::Var::get
56/// [`map`]: crate::Var::map
57/// [`IntoVar`]: crate::IntoVar
58/// [`merge_var!`]: crate::merge_var
59#[macro_export]
60macro_rules! expr_var {
61    ($($expr:tt)+) => {
62        $crate::__expr_var! { $crate, $($expr)+ }
63    };
64}
65
66///<span data-del-macro-root></span> New variable from an expression with interpolated vars that produces another variable.
67///
68/// This macro is very similar to [`expr_var!`], it just expect an expression that produces another variable and flattens it.
69#[macro_export]
70macro_rules! flat_expr_var {
71    ($($expr:tt)+) => {
72        $crate::expr_var! {
73            $crate::VarEq($($expr)+)
74        }.flatten()
75    };
76}
77
78#[doc(hidden)]
79pub use zng_var_proc_macros::expr_var as __expr_var;
80
81use crate::{IntoVar, MergeInput, Var, VarValue};
82
83#[doc(hidden)]
84pub fn expr_var_into<T: VarValue>(expr: impl IntoVar<T>) -> Var<T> {
85    expr.into_var()
86}
87
88#[doc(hidden)]
89pub fn expr_var_as<T: VarValue>(var: impl MergeInput<T>) -> Var<T> {
90    var.into_merge_input()
91}
92
93#[doc(hidden)]
94pub fn expr_var_map<I: VarValue, O: VarValue>(input: impl MergeInput<I>, map: impl FnMut(&I) -> O + Send + 'static) -> Var<O> {
95    input.into_merge_input().map(map)
96}