Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the 'n' specifier for locale-dependent floating point formatting #1084

Closed
vitaut opened this issue Mar 17, 2019 · 16 comments
Closed

Add the 'n' specifier for locale-dependent floating point formatting #1084

vitaut opened this issue Mar 17, 2019 · 16 comments

Comments

@vitaut
Copy link
Contributor

vitaut commented Mar 17, 2019

No description provided.

@BillyDonahue
Copy link
Contributor

BillyDonahue commented Jun 9, 2019

I’d be a little hesitant to use ‘n’ because ‘n’ already means something to printf (which would be good to have in libfmt actually). Can the locale sensitivity be added with a modifier instead, like printf’s “I”?

For floats there are already several different styles. There’s {a,e,f,g, and A,E,F,G}. They could all use a locale option, so it seems much better to have locale as an option to the existing specifiers rather than reserving 8 more letter codes.

I may not be understanding the Issue correctly, in which case I apologize. :)

Update: Oh. You already have “n” doing locale for integers and you are proposing expanding it to cover floats. In that case, though, how would you distinguish which float style, among { a,e,f,g,A,E,F,G}, is implied by the “n” specifier?

@vitaut
Copy link
Contributor Author

vitaut commented Jun 10, 2019

This issue is about fmt::format which is modeled after Python's str.format where n denotes locale-specific formatting. fmt::printf can potentially support n although it's a questionable API which should be done differently in a type-aware environment.

how would you distinguish which float style, among { a,e,f,g,A,E,F,G}, is implied by the “n” specifier?

Good question. I was thinking along the lines of having some specifier like l that you suggested but I don't know if it's actually useful. Do you have a use case for this?

@en-em
Copy link

en-em commented Jul 3, 2019

It makes no sense to add n or any other special locale aware format specifier. fmt has an optional locale argument. If it is provided, the user obviously wants locale-aware output.

@vitaut
Copy link
Contributor Author

vitaut commented Jul 3, 2019

The locale is always there, the locale argument only overrides the global one. It shouldn't change the semantics of format specifiers.

@en-em
Copy link

en-em commented Jul 3, 2019

The locale is always there

I know it currently works this way, my point is that it isn't necessarily a good design.

@vitaut
Copy link
Contributor Author

vitaut commented Jul 3, 2019

The current design inherited from Python has the number of advantages. Most importantly it's known statically whether locale is used or not for a given replacement field. Making it a runtime decision based on passing a locale as an argument would penalize the common case and muddy the semantics of specifiers. In practice there is little reason to use format with an explicit locale. Normally applications either don't use a locale (e.g. when writing JSON or XML) or use a global locale (for user messages). There are some use cases for an explicit locale, but they are rare.

That said, if you want to experiment with a different design you could easily do so. {fmt} provides building blocks that can be used to implement formatting functions where behavior changes depending on the locale argument or any other state.

@en-em
Copy link

en-em commented Jul 4, 2019

There are many ways to solve this problem, but in my humble opinion introducing special locale-aware format specifiers is the worst imaginable one. They are unfamiliar, they don't buy you any expressivity, and they will give you either no performance advantage or only a negligible advantage but for a price of code bloat. But hey, it's your library...

@foonathan
Copy link
Contributor

What about a wrapper type:

fmt::format("{} vs {}", fmt::locale_aware(3.14), 3.14)

For me it would print: 3,14 vs 3.14

@vitaut
Copy link
Contributor Author

vitaut commented Jul 4, 2019

for a price of code bloat

There will be no code bloat.

@vitaut
Copy link
Contributor Author

vitaut commented Jul 4, 2019

The n specifier is working with floating-point arguments now.

@vitaut vitaut closed this as completed Jul 4, 2019
@YannickJadoul
Copy link

I'd love to use this! I found out a while ago it's quite involved to efficiently turn a double into a locale-independent string.

Just wondering: any idea how soon this feature would be released? Or should I try using the master branch?

@vitaut
Copy link
Contributor Author

vitaut commented Jul 29, 2019

Just wondering: any idea how soon this feature would be released? Or should I try using the master branch?

I started working on preparing the next release but don't have specific release date yet, so I recommend using the master branch which is fairly stable.

@YannickJadoul
Copy link

Amazing! Thanks for the quick reply :-)

@dlaugt
Copy link
Contributor

dlaugt commented Nov 1, 2019

It does not respect the thousand separator from the locale.

>>> from locale import setlocale, LC_ALL
>>> setlocale(LC_ALL, 'en_US')
'en_US'
>>> '{:n}'.format(1234)
'1,234'
>>> '{:n}'.format(1234.56)
'1,234.56'
setlocale(LC_ALL, "en-US");
fmt::format("{:n} {:n}", 1234, 1234.56);
// gives 1,234 1234.56

Could we have also the thousand separator for floating number like python?

@vitaut
Copy link
Contributor Author

vitaut commented Nov 1, 2019

Sure. PRs are welcome.

@dlaugt
Copy link
Contributor

dlaugt commented Nov 2, 2019

Right, for now, I have added a new issue #1392 for this concern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants