elixir-lang / elixir-lang.github.com

Website for Elixir
elixir-lang.org
355 stars 824 forks source link

Update `String.split/2` into `String.split/3` #1768

Closed zorn closed 2 months ago

zorn commented 2 months ago

There is no String.split/2, best I can tell.

https://hexdocs.pm/elixir/String.html#split/3

But String.split/3 does behave as the blog post explains.

iex(1)> String.split("")
[]
iex(2)> String.split("", ",")
[""]
josevalim commented 2 months ago

That's a bug in Elixir. I will take a look at it. :) Thanks for noticing.

sabiwara commented 2 months ago

There is no String.split/2, best I can tell.

Actually there is a String.split/2, which corresponds to the default options \\ []. Hex docs shows it properly, and as you mentioned yourself you are able to call String.split("", ",") 🙂

The purpose of defaults is precisely to define several arities with one signature.

sabiwara commented 2 months ago
iex(1)> String.split("")
[]

That's a bug in Elixir.

@josevalim I agree this is inconsistent with String.split/2/3, but it seems intentional looking at the tests and code.

Removing the trim seems like a breaking change, should we document the trimming behavior instead?

sabiwara commented 2 months ago

Random thought: we could change String.split/2/3's pattern to pattern() | Regex.t() | :whitespace, deprecate String.split/1, and String.split(s) would have to be replaced by String.split(s, :whitespace, trim: true). This could also expose whitespace -- non_breakable and make it work with more options?

josevalim commented 2 months ago

Yes, agreed, this is intentional.

When it comes to provide a better API, a general golden rule is to not have the return type changed by options. So the real issue here is that the return type depends on the option trim: true | false. So what we would want to do in the future is to deprecate the trim option and introduce split_and_trim, which may return an empty list.

:whitespace could be a choice if we want to allow whitespace to be used with other options.

But for now, I think we are good, especially because String.split/2 does behave exactly as described in the post. :)

zorn commented 2 months ago

The purpose of defaults is precisely to define several arities with one signature.

Interesting. This is kind of a new concept for me. In the past, if a function accepted three arguments, even if the third one was optional, I would still always use the /3 declaration.

But as you say, because the third argument is optional, the language infers that there is a /2 version.

As seen trying to tab complete the function name in an iex session:

iex(5)> String.split
split/1       split/2       split/3       split_at/2    splitter/2    splitter/3

Thanks for the quick responses and guidance. 👍