10

With new versions of Rust, you can simplify structure initialization like this:

Foo {
    a: a,
    b: b,
}

to this

Foo { a, b }

Is it possible to do something similar for format!/println!-like macros?

For now I need to write it like this:

let a = "a";
let b = "b";
write!(file, "{a} is {b}", a = a, b = b).unwrap();

Is it possible to write my own macros with an API like this:

let a = "a";
let b = "b";
my_write!(file, "{a} is {b}", a, b).unwrap();
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
user1244932
  • 7,352
  • 5
  • 46
  • 103
  • I'm not sure that I understand what you are asking, but you don't need named formatting arguments, you can stick to positional arguments: `write!(file, "{} is {}", a, b)`, or `write!(file, "{0} is {1}", a, b)`. – E_net4 Jul 27 '17 at 17:03
  • @E_net4 No, I not need numbers, I want names, in have ~ 5 arguments so I need name for them, like `{long_word}`, `{another_long_word}` – user1244932 Jul 27 '17 at 17:05
  • You may wish to read the documentation on [std::fmt](https://doc.rust-lang.org/stable/std/fmt/index.html). The code that you wrote does not seem to do what you want. Can you create a [MCVE] that shows how you are currently formatting the struct? – E_net4 Jul 27 '17 at 17:08
  • I think that using the *variable* `a` with the *string value* `"a"` is likely confusing your example, especially with the text `"{a} is {b}"`. Try using something concrete like `name` and `age` instead. – Shepmaster Jul 27 '17 at 17:16
  • 1
    @E_net4 The question is, does the formatter allow `a` to be intepreted as `a = a` in formatters, like it allows `a` to be short for `a: a` in struct initializers. The answer is No AFAIK? – loganfsmyth Jul 27 '17 at 17:16
  • @loganfsmyth Indeed, it took me a while to understand the question. Thanks. As for its feasibility, I haven't managed to wrap my head around it yet. :) – E_net4 Jul 27 '17 at 17:20
  • @loganfsmyth I know that it impossible, the question is it possible to create wrapper for std format macroses that do what I want. – user1244932 Jul 27 '17 at 17:24
  • if you're lazy you can just stuff them into a tuple and `{:?}` it since tuples implement Debug – the8472 Jul 27 '17 at 18:45

2 Answers2

12

RFC 2795 has been accepted and implemented. Starting in Rust 1.58, you will be able to go beyond your desired syntax:

write!(file, "{a} is {b}").unwrap();

Before then, you can write your own wrapper around println! and friends:

macro_rules! myprintln {
    ($fmt:expr, $($name:ident),*) => { println!($fmt, $($name = $name),*) }
}

fn main() {
    let a = "alpha";
    let b = "beta";
    myprintln!("{a} is {b}", a, b);
}

This will likely always be limited compared to the full formatter macro, but it may be sufficient for your case.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
-1

As of 1.5 this is the closest you can get natively.

my_write!(file, "{} is {}", a, b).unwrap();

Additionally as Shepmaster pointed out my answer will eventually become obsolete (I'll try to remember to remove it when that happens). If you want to keep an eye on the (to be implemented) syntax they propose you can check this github ticket they linked

Chris Rudd
  • 709
  • 7
  • 13
  • 2
    OP asked this question on 2017-07-27; [Rust 1.18 was the stable release at the time](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1180-2017-06-08). In the question, they are already using the syntax you propose (`write!(file, "{a} is {b}", a = a, b = b).unwrap();`). The specific question is about removing the duplication of `a = a`. – Shepmaster Aug 24 '18 at 03:11
  • 1
    I gave my upvote because I just wanted to know this answer and google found it :) – matiu Jan 28 '21 at 12:02
  • @Shepmaster that is not the syntax I demonstrated, though I'm open to making adjustments since it seems you may have misunderstood (I feel clarity is important). If you look the X does not use the = allowing for a more concise declaration. Granted it is without the explicit naming (which prevents repetition and out of order assigning) but the op didn't request that. Additionally I explicitly mentioned this is for 1.5 (not the 1.18 the OP was using). I added my answer because this still shows up in searches on google. – Chris Rudd Apr 28 '21 at 19:04
  • *but the op didn't request that* — sure they did: "Is there a way to **pass named arguments** to format macros". The syntax `{}` isn't a named argument, it's a *positional* argument. They even show what example they'd like: `my_write!(file, "{a} is {b}", a, b)`. – Shepmaster Apr 28 '21 at 19:25
  • *I explicitly mentioned this is for 1.5 (not the 1.18 the OP was using)* — sure, but why? The syntax you show has existed since 1.0. Why the arbitrary choice of 1.5? – Shepmaster Apr 28 '21 at 19:26
  • Because that's the version I tested it on, and for which I had documentation. If you provide me a link to the original update and documentation I'd be happy to update the reference – Chris Rudd Apr 30 '21 at 19:06
  • I see, so what you're saying is the answer I proposed was already mentioned in comments and rejected by the OP? – Chris Rudd Apr 30 '21 at 19:17