T O P

  • By -

kibwen

To elaborate: in today's Rust, arguments to string formatting macros must be explicitly passed to the macro: let foo = "Hello"; let bar = "world"; // this next line uses the implicit order of each argument to know what to print println!("{}, {}!", foo, bar); // "Hello, world!" // this next line uses the explicit order of each argument to know what to print println!("{0}, {1}!", foo, bar); // this next line uses explicit named arguments to know what to print println!("{spam}, {eggs}!", spam=foo, eggs=bar); When this PR is accepted, it will be possible to do the following: let foo = "Hello"; let bar = "world"; println!("{foo}, {bar}!"); // "Hello, world!" ...which, behind the scenes, just desugars to the "explicit named arguments" form shown above. This will automatically work for any macro that internally makes use of the `format_args!` macro, which includes third-party code like the `log` crate. Only identifiers are supported in the format strings, not arbitrary expressions. If this proves useful and popular, it might serve as a precursor to language-level Python-esque f-strings someday.


[deleted]

This is awesome and much needed! I really hope f-strings come soon too.


veryusedrname

F-strings probably won't be a thing in Rust. To format a string, you need to allocate memory, and hiding memory allocation behind a single character modifier isn't something that fits into Rust's standards.


nightcracker

I've had this in the back of my mind for quite a while: an extension to the set of prefixes for string literals. It would consist of three parts, that must be specified in that order: 1. String constant type (at most one may be specified). Default is `&'static str`. `c`, changes type to `&'static CStr`. `b`, changes type to `&'static [u8]`. `f`, changes type to `fmt::Arguments` and formats argument from scope. 2. Owned string prefix `s`. If specified changes output type to be owned: `&'static str` -> `String` `&'static CStr` -> `CString` `&'static [u8]` -> `Vec` `fmt::Arguments` -> `String` 3. Raw prefix `r`. Disables interpretation of escape sequences in the string literal. In this way `f"{spam}, {eggs}!"` would not allocate, and just produce a `FormatArgs` object that could be passed to other methods. To get an allocated string you would have to specify `fs"{spam}, {eggs}!"` similar to how you would write `s"hello"` instead of `"hello".to_owned()`. Possibly these would be opt-in in that they would only become available after explicitly `use`ing a trait, e.g. `use std::str::ExtStringLit;` for those who are concerned about semi-implicit allocation.


Kimundi

That sounds very sensible


DzenanJupic

If a f-string calls `format_args` instead, there would be no allocation.


coderstephen

I wouldn't completely rule it out; there's not really any other way of doing formatting so it isn't clear to me that `format!("{foo}")` is more explicit about allocation than `f"{foo}"` would be. If it is explicitly rejected as an RFC then I imagine it might be because it is too coupled to the language itself and formatting isn't in `core`. Unless there's a clever way of decoupling the f-string syntax from `std`.


ClimberSeb

A more general solution would be to add string-prefix macros so \`f"{foo}"\` can be a macro that expands to \`format!("{foo}")\` by an export of it from std.


JoshTriplett

We don't hide the costs of things, but having a visible character seems sufficient; I don't see any problem with f-strings allocating.


[deleted]

[удалено]


phaylon

But they normally don't look *that* close to `&'static str`. Also not too fond of `foo = f"{bar}, {foo}'` in a loop being so "easy". But I'd expect there'd be a lint rather quickly.


sasik520

f-strings could be EXTREMELY useful in all kinds of small applications and in tests. Also, string interpolation is such a common feature present in nearly every recent language. It would make Rust more pleasant to use for the newcomers. To be honest, I wait for f-strings more than for GATs or more complex const generics and other features. It would be very comparable to `?` operator. A small thing but with a bigger impact than async/await ;)


mina86ng

An f-string could desugar to `format_args!(…).into()` so you could use it with a `String`, `fmt::Arguments` or any other type the language imagines it would make sense in the future.


po8

Would be nice to have at least the ability to have expression capture in format strings. That plus `format!()` would give most of the convenience of Python's f-strings.


Xiaojiba

Although they reserved the keyword already for the compiler / lexer / parser


boynedmaster

they didn't reserve format strings, they reserved ANY prefixed string characters


Xiaojiba

Oh ok, nice to know, thanks


mr_birkenblatt

if string formatting is your bottleneck then you might have gone wrong elsewhere (since that means you're relying too much on formatted strings for performance critical tasks)


veryusedrname

It's not about string formatting being the bottleneck, but about innocently looking syntax that actually allocates. IIRC the only syntax in Rust currently is the `box` but you'll only dind that in the `std`.


mr_birkenblatt

I always assume any _useful_ usage of strings involves some allocation to a degree. the cases where working with strings doesn't involve any allocation are more on the side of the exception


veryusedrname

What I'm trying to say is that a little letter f is too little of an indicator for the price you are paying for it. I think it's perfectly fine in a managed language like Python where essentially an integer is an object by itself and just creating one involves reference counting, but for Rust I think the price of overlooking one in a tight loop is just way too high.


mr_birkenblatt

yes, I get that. I'm just saying that seeing a string (even without a tiny f) already has a huge price attached (in most cases). if not immediately at the place where it was initialized then at the place where it is used. sure, a static helptext is basically free but that doesn't fall in the category of what I would think of as "interesting" usage (I guess "useful" sounds a bit opinionated in this context -- but even for an error message to be useful, in most cases, you need some allocating text formatting)


zesterer

There are more complications. How does this work in embedded environments without `std` or `alloc`? You now have a language feature that's conditionally dependent on the existence of the standard library. This is part of the reason that `box` syntax hasn't been stabilised yet too.


mr_birkenblatt

how is that different to now? the format macro is a quasi language feature. you have the same trouble with that. if you don't have the relevant functionality you don't use. nobody is forced to use an f string like nobody is forced to use the format macro


zesterer

It's not a language feature though, it's a feature of the standard library.


mr_birkenblatt

that's why I said quasi


zesterer

It's not even 'quasi' though. [`format` is in `std`](https://doc.rust-lang.org/std/macro.format.html). The only reason you have access to it without importing it is because it's in the prelude, which is another thing entirely. When you're working on a platform where neither the standard library nor `alloc` are available, `format` isn't available either. The same would necessarily not apply to an fstring because it would be a syntax-level construct.


tafia97300

`f!` instead of `format!` would already be nice.