mikl

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 String.Casing.titlecase_once(word, nil), although this is a little undocumented). Don’t do this, see comment from josevalim below.

Most Liked

mikl

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

josevalim

Creator of Elixir

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. :slight_smile: String.Casing is private API and may change at any time, breaking your code.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Nice! No point in slicing twice though:

    <<first_grapheme::utf8, rest::binary>> = string
    String.capitalize(<<first_grapheme::utf8>>) <> rest

EDIT: Fixed a bug pointed out by @adamu thanks!

Where Next?

Popular in Discussions Top

Fl4m3Ph03n1x
Background This question comes mainly from my ignorance. Today is Black Friday, one of my favorite days of the year to buy books. One boo...
New
chuck
Let me start by stating an assumption: Phoenix is a great approach to building REST APIs. There are many reasons for this, but I will ass...
New
PragTob
Hey everyone, this has been brewing in my head some time and it came up again while reading Adopting Elixir. GenServers, supervisors et...
New
RudManusachi
What configs will make sense to put to runtime.exs? – A bit of how I configure apps: I have generic configs in config/config.exs, dev...
New
100phlecs
Are there any downsides, like perf issues, to putting all functional components in CoreComponents as long as you prefix it with the conte...
New
griffinbyatt
Sobelow Sobelow is a security-focused static analysis tool for the Phoenix framework. For security researchers, it is a useful tool for g...
New
opsb
We’re considering our architecture from a viewpoint of scaling our traffic heavily over the next 6 months. Our current deployment is runn...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54120 245
New
fireproofsocks
This is more of a general question, but I’m wondering how other people in the community think about the pattern matching in function sign...
New
kostonstyle
Hi all How can I compare haskell with elixir, included tools, webservices, ect. Thanks
New

Other popular topics Top

lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New

We're in Beta

About us Mission Statement