mikl
String.capitalize() should have a “leave the rest of the word alone” option
I wanted to capitalize a string, and tried using String.capitalize().
That generally works well, until you try to capitalize a word like ATM, which then comes out as Atm.
That is correct according to the documentation, as it states that String.capitalize() does this:
Converts the first character in the given string to uppercase and the remainder to lowercase according to
mode. [emphasis mine]
Now that is not what I expected from a function called capitalize(). I naïvely thought that would only touch the first letter, as String.capitalize does in Python and similarly named functions does in other programming languages.
Elixir is probably mimicking Ruby here, and the point of this post is not to say that the implementation is wrong, it’s too late to change now anyway.
However, it would be handy if there was a :first_letter_only or similar mode, that would only touch the first letter, so developers everywhere won’t have to write their own capitalize function to be able to safely capitalize words without mangling abbreviations.
(If you come across this topic wanting to just capitalize the first letter, you can use Don’t do this, see comment from josevalim below.String.Casing.titlecase_once(word, nil), although this is a little undocumented).
Most Liked
mikl
Since this is a fairly common thing to do, and one with a bunch of tricky edge cases, wouldn’t it be the kind of thing that belongs in the standard library?
At least as a relative newcomer to Elixir, I find it a bit surprising to have to write my own String.cap_first() implementation, because the language does not provide one.
Anyway, Erlang’s titlecase() (added in OTP 20) function works for my use case at least, it can be called like this :string.titlecase(text) – although you should probably have a wrapper for it to filter out non-binary strings and such things.
josevalim
The reason why we do first letter only is because Unicode has specific rules that consider the rest is being lowercased.
For the behaviour that you want, you should be able to implement it using String.next_grapheme, getting the first part, upcasing it an then concatenating the rest. Just make sure to take into account empty strings.
Don’t do this.
String.Casing is private API and may change at any time, breaking your code.
Popular in Discussions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









