[][src]Macro lazy_format::semi_lazy_format

macro_rules! semi_lazy_format {
    (match ($condition:expr) {
        $(
            $(|)? $match_pattern:pat
            $(| $trailing_pattern:pat)*
            $(if $guard:expr)?
            => ($pattern:literal $($args:tt)*)
        ),* $(,)?
    }) => { ... };
    ($pattern:literal $($args:tt)*) => { ... };
}

Lazily format something by eagerly evaluate the arguments ahead of time, then storing them and formatting them at write time.

This macro is essentially the same as format!, except that instead of formatting its arguments to a string, it evaluates them and captures them in an opaque struct, which can be formatted later. This allows you to build up formatting operations without any extra allocations or formatting calls.

The return value of this macro is left deliberately unspecified and undocumented. The most important thing about it is its Display implementation, which executes the deferred formatting operation. It also provides Clone and Copy if those traits are implementated in all of the evaluated formatting arguments.

Unlike lazy_format, this macro is partially lazy, in that it evaluates its argument expressions and stores the values to be formatted later. This is often more convenient, especially if the formatted values are simple data types like integers and &str. This can also make using the value easier, as its less likely to capture locally scoped variable or references and therefore have lifetime issues.

use std::fmt::Display;
use std::mem::{size_of_val, size_of};
use lazy_format::semi_lazy_format;

fn get_formatted() -> impl Display {
    let x: isize = 512;
    let y: isize = 512;
    semi_lazy_format!("value: {v}, again: {v}", v = (x + y))
}

let result = get_formatted();

// At this point, addition expression has been performed. `result`
// captures only the result of the expression, rather than the two
// operands.
assert_eq!(size_of_val(&result), size_of::<isize>());

let result_str = result.to_string();
assert_eq!(result_str, "value: 1024, again: 1024");

semi_lazy_format supports match-like formatting expressions, with the same syntax as lazy_format. In this case, only the condition is evaluated ahead of time; the match itself is deferred until the object is written, due to limitations in the type system.


use std::fmt::Display;
use std::mem::{size_of_val, size_of};
use lazy_format::semi_lazy_format;

fn get_formatted() -> impl Display {
    let opt1 = Some(10 as isize);
    let opt2 = Some(20 as isize);
    let opt3 = Some(30 as isize);

    semi_lazy_format!(match (
        opt1.and(opt2).and(opt3)
    ) {
        Some(value) => ("value: {}", value),
        None => ("no value."),
    })
}

let result = get_formatted();
assert_eq!(size_of_val(&result), size_of::<Option<isize>>());

let result_str = result.to_string();
assert_eq!(result_str, "value: 30");