Why can't I return `format_args` from a closure?

(Playground link)

use itertools::Itertools;

fn main() {
    let v = vec![1,2,3,4,5];
    // why this line doesn't work?
    v.iter().map(|it| format_args!("x{}", it)).intersperse(format_args!(", ")).for_each(|args| println!("{}", args));
    
    // whereas this line work
    println!("{}", v.iter().format_with(", ", |it, f| f(&format_args!("x{}", it))));
}

The error message reads "returns a value referencing data owned by the current function", it is not owned by the current function, it is owned by the vector. What's wrong with the code?

1 Like

The macro evaluates each expression argument into macro-generated locals, then passes references to those in the Arguments structure. It seems simple in your case that it could just use your given reference, but that doesn't generalize.

1 Like

Oh, I see. In this case, is there any way to tell the macro to use the expression as a reference directly?

1 Like

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5f189aaf12f4e9dcb70d5a0aabc3d98f

You can create internal type which implements std::fmt::Display, and return it from a function using impl std::fmt::Display + 'a.
With this way, You can return to-be-formatted objects without rendering them too earlily.
However, this requires lots of boilerplates and would not be useful for some cases.

That part can be factored out by being generic over a formatting closure, and a macro that converts format!-like syntax into such a closure:

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.