← Back to context

Comment by lenkite

3 days ago

Say if you were designing a new language and wanted to include string formatting as a feature. Would you personally choose Python f-strings or C-style format strings or Rust-style formats ?

In terms of format string syntax, Rust is extremely similar to Python (and C++'s new std::format is also similar). So in that sense it seems Python-style "{name:fmt}" has won. Though the others don't support arbitrary expressions inside of the string.

On the other hand, you have formatting as an expression that evaluates to a string like f"..." in Python, vs formatting as a set of functions that take the same input format but do various things like printf/snprintf/write!/format!/std::print/std::format... Here it seems Python's approach had too many drawbacks, considering they just added formatted templates t"..." that don't evaluate to a string.

If I were to design a new language, I would use a Python-like "{expr:fmt}" syntax for formatting, but I would make it evaluate to some sort of FormatTemplate object that code can inspect.

  • > Here it seems Python's approach had too many drawbacks, considering they just added formatted templates t"..." that don't evaluate to a string.

    That's not a fair characterization at all, since the plan was always to add something like the t"" strings. Having a version that immediately evaluates to a string is convenient, and adds very little complexity either at the implementation level or conceptually.

    • I don't think that was always the plan. Certainly the proposal has been tossed around for a while, but the overall historical evidence paints a different picture for me.

Can you get away with just f-strings? Python also has `string.format` for situations where the string needs to be built dynamically.

Are there languages which only have an f-string-like feature without a `string.format` equivalent?

t-strings with str.format-like limitations on what can be substituted in, except the t is actually an operator that applies at compile time when its argument is a literal and at runtime otherwise. And then f is another such operator that sugars over a standard library format(t '{...}') call.

(I've been thinking about this for a while, actually. Since PEP 751 was still in discussion.)