80

In Ruby I could do this.

aaa = "AAA"
bbb = "BBB #{aaa}"

puts(bbb)

> "BBB AAA"

The point of this syntax is eliminating repetition, and making it to feel like a shell script - great for heavy string manipulation.

Does Rust support this? Or have plan to support this? Or have some feature which can mimic this?

eonil
  • 83,476
  • 81
  • 317
  • 516

3 Answers3

81

Rust has string formatting.

fn main() {
    let a = "AAA";
    let b = format!("BBB {}", a);
    println(b);
}
// output: BBB AAA

In the Rust version, there is no additional repetition but you must explicitly call format!() and the inserted values are separated from the string. This is basically the same way that Python and C# developers are used to doing things, and the rationale is that this technique makes it easier to localize code into other languages.

The Rust mailing list has an archived discussion ([rust-dev] Suggestions) in which the different types of string interpolation are discussed.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • 16
    It seems the discussion didn't continue much. Sad. – eonil Jan 24 '14 at 05:10
  • @ChrisMorgan: That's just background information. The background information hasn't changed in the past 23 months, unless you have something you'd like to share. – Dietrich Epp Jan 24 '14 at 06:26
  • 10
    You can also use `format!("BBB {name}", name = a)`. (It would probably actually be possible to use the same parsing & macro infrastructure as `format` uses to achieve `inline_fmt!("BBB {a}")`, although hygiene may require some tricks to work around.) – huon Jan 24 '14 at 11:09
  • @DietrichEpp: in 23 months a lot has changed about the language; things that were considered infeasible or inappropriate then may not be any more. For example, back then printf-formatting was the way things were done while now it is the new style formatting. There is also a much larger community now. These all change the dynamics considerably. – Chris Morgan Jan 24 '14 at 23:35
  • @ChrisMorgan: We're talking about different things here. I'm talking about the background information: "How do other languages implement string formatting, and why would we choose one syntax over the other?" That hasn't changed. – Dietrich Epp Jan 24 '14 at 23:42
  • 10
    Both Python and C# have since added string interpolation. Python: `f'{a} times {b} is {a * b}.'`, C#: `$"{a} times {b} is {a * b}"` – Ghost4Man Dec 20 '19 at 14:57
  • 3
    Here is a more recent discussion on this topic: https://github.com/rust-lang/rfcs/issues/1250. This answer currently doesn’t feel relevant anymore, since it justifies Rust’s string formatting as being about portability to other languages, which is no longer true – Python, C#, JS, etc, all have syntaxes closer to Ruby than the Rust one. – Thibaud Colas Jan 27 '20 at 07:14
  • This doesn't work on constants (at the time of this writing). – code_dredd Aug 10 '20 at 23:59
77

This is available since Rust 1.58! Here's the syntax:

let (person, species, name) = ("Charlie Brown", "dog", "Snoopy");

// implicit named argument `person`
print!("Hello {person}");

// implicit named arguments `species` and `name`
format!("The {species}'s name is {name}.");

RFC 2795 is the original proposal.

legends2k
  • 31,634
  • 25
  • 118
  • 222
eonil
  • 83,476
  • 81
  • 317
  • 516
  • 4
    IMO coming from JS that RFC is . The mentioned full-interpolation syntax `{( )}` has awful readability, especially compared to `${ }`, and the author has a mysteriously strong bias against supporting interpolation of arbitrary expressions. Instead they'd rather wrestle with the ways string concatenation throws a wrench into the macro formatting system. Having a string literal syntax where arbitrary expressions can be embedded in `${ }` is just so much simpler. – Andy Nov 30 '21 at 06:42
  • 22
    It was release in Rust version 1.58.0 – Rodrigo Stuchi Jan 13 '22 at 18:46
  • 1
    @Andy, you are missing the point of Rust's type system, safety, and compile time macros. See [this SO answer](https://stackoverflow.com/a/32580595/267874) for details. – Paul-Sebastian Manole Dec 01 '22 at 14:02
  • 3
    I don't see how it would be impossible to type check arbitrary expressions embedded inside string template literals. It seems like the main problem is they want to stick with using macros to do formatting on a plain old string template instead of adding a new string template literal syntax to the language grammar. – Andy Dec 01 '22 at 18:07
  • @Andy The thing is, type checking is hard, lifetime checking is hard. And when it's too hard, you can't tell the compiler "trust me, this *value* is of this type" like in TypeScript, happily confusing casting and annotation because they don't matter anyway. Instead, in most cases for types and all cases for lifetimes, you gently tell it :"could we make it so this *variable* is of this type ?". And if you can, you have type safety. So forcing to use a variable prevents the risk of needing a refactor for an obscure reason if the expression is for example an &str – 4xel Aug 30 '23 at 11:36
  • @Andy But I think the main reason they are cautious about it, beyond keeping scoping and type analysis simple for both human and compiler, is design space. Expressions can already contain quotes, braces and even colon. I can't think of a collision, but break label (`'lbl : {` ...) comes dangerously close (is that a label colon, or a formatting one ?). Now a lot of things are still possible, but Rust devs are extremely cautious when it comes to commit to new features and syntaxes. They probably learned from JavaScript willy-nilly adding every next cool fad and falling into legacy hell. – 4xel Aug 30 '23 at 11:44
44

As of Rust 1.58, you can take advantage of captured identifiers in format strings. That lets you do stuff like this:

let msg = "here";
let s = format!("Abc {msg}");  
println!("Hi t{msg}");   // prints "Hi there"
println!("{s}");         // prints "Abc here" 

This feature can be seen as a subset of string interpolation. Expressions like format!("Abc {a+b}") are not supported and it's unclear whether such a feature will ever be added. There have also been discussions on adding a subset of expressions for dotted paths, as in format!("Abc {foo.bar}").

Also note that the Rust 2021 Edition makes room for future additions to the language, such as f"hello {name}", which would allow for a much more concise string interpolation, comparable to most other modern languages.

at54321
  • 8,726
  • 26
  • 46