Convert 'charlists' into ~c"charlists"

Yes and no. I helped people learn Elixir off-forum and while iex printing ~D[2020-07-10] does tell them that this is something special they have to look into, on the other side of the coin iex does not make it easy to search for sigil’s docs or understand what a sigil even is.

Try typing e.g. h ~S in iex – you get an error. You have to know what you are looking for in the first place and type h sigil_S which IMO kind of defeats the purpose of having something that can guide the learner without them having to go to a website [to learn about sigils].


I propose this be expanded to 3 action points:

  • Print charlists as integer lists by default in iex
  • Do use the new canonical form of ~c"something"
  • Change iex and/or the h helper so that it can understand queries like h ~c

Having all three would IMO allow people to self-onboard. They type ‘abc’ in iex and see ~c"abc" and then intuitively they would do h ~c and would get an explanation. Of course that assumes they know about iex and h in the first place, sure :smiley: but hey, we have to start somewhere.

4 Likes

That’s not great, very true. But it’s imo still a lot better than 'abc', which to a new elixir developer likely just means “string”. At best they find one of the many “list turned string” topics on the forum or they might find a lot or irrelevant information about binaries.

I think there should be an options for printing charlists as lists, as erlang strings and both.
It might be useful when using erlang libs.

If the goal is just to make charlists as accessible as possible to newcomers, I like the idea of making the default inspection of charlists show both the list form and what it looks like as a charlist:

iex> 'some text'
[115, 111, 109, 101, 32, 116, 101, 120, 116] #'some text'

I’m not sure the implications of having an inspected form that is half-comment, but I feel like something like that would make it very clear what’s going on. It would be a little verbose, but more experienced folks could just configure it to something else.

This isn’t mutually exclusive with embracing the sigil form, either.

3 Likes

This might be integrated with the upcoming dbg facility, maybe?

What I remember is that we discussed this very early on: https://groups.google.com/g/elixir-lang-core/c/_pAjPEayLLI/m/kIyPG8HtAQAJ

And it was abandoned because rewriting everything manually, at least in the Elixir codebase, was too cumbersome. The formatter solves that. :slight_smile:

3 Likes

~c is not valid syntax but h ~c/anything/ will work, with any enclosing, from Elixir v1.14. And there is also the i helper. :slight_smile:

2 Likes

Ah, that’s great then! Thanks for clarifying.

Is that a part of first release candidate, master branch or still only planned? If it’s part of release candidate then it does not work in my asdf environment:

$ iex
Erlang/OTP 25 [erts-13.0.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]

Interactive Elixir (1.14.0-rc.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> h ~c/anything/
The "h" helper expects a Module, Module.fun or Module.fun/arity, got: 'anything'
If instead of accessing documentation you would like more information about a value or about the result of an expression, use the "i" helper instead

Edit: I found it working on master branch using master-otp-25 from asdf.

Also can’t compiler solve ~c by expanding having in mind that’s doing same thing with variables?

warning: variable "example" does not exist and is being expanded to "example()", please use parentheses to remove the ambiguity or change the variable name

I’m not strongly opposed. However, Elixir to date has largely avoided changes that introduce “churn” to existing codebases except when really required for big important changes, and I for one have loved that about the ecosystem.

Even if the changes required are more or less automatic due to leveraging the formatter, this update to Elixir would still add another thing to do for any older codebases before it can compile with a newer version of Elixir. Should be fine for a lot of software, but imagine for example some piece of code sitting on GitHub that has simply been “done” for a while, the maintainer is no longer really active, etc. This update might mean lots of otherwise unnecessary forks of such a library.

The current difference between double and single quotes seems like a small one-time thing that takes a couple of minutes out of your initial Elixir learning experience to get through. Not all languages need to be the same or meet novices’ expectations, and there are other things that will tend to break expectations and can’t reasonably be changed (for example, every statement returning what it evaluates and thus no need for an explicit “return” keyword).

I do think better help for charlists in IEx would be great.

3 Likes

This is not a breaking change. Old code will still work fine, albeit with a warning, and effective support for single quotes would be removed only in 2.0, which would be several years from now (if it happens).

6 Likes

Seems that I misunderstood, I thought part of the motivation was to allow strings (binaries) to be represented using single quotes as in other languages. If it’s not a breaking change then I see no downsides to it. Thanks for the clarification!

1 Like

Yes, I think it would improve learning (a lot) and user experience (slightly) if there were clear warnings for single quotes.

To be honest, equally confusing.

No problem, my initial message was not as clear as it could have been. :slight_smile: Single quotes would warn for now and likely have no use whatsoever in future versions.

1 Like

I think this would be a good change as it would help to remove a point of confusion that some folks new to the language seem to stumble over quite a bit – the difference between charlists and binaries being a little more subtle than perhaps it should be.

Good idea!

1 Like

Hello, I found this thread after getting charlist printed again in test failures. Is there any way to change the default, globally, everywhere, including tests? I’ve found IEx.configure(inspect: [charlists: :as_lists]) but it’s not enough.

More context: I’m working with NimbleParser, parsing text with a lot of integers, as values, example "80-90 HR" and I’m currently converting this into a tuple as {80, 90, "HR"} just to avoid it being printed with ~c"".

1 Like

There may be a better way, but I think you could do this with Inspect.Opts.default_inspect_fun/1 by modifying the inspect opts that are passed.

1 Like

Thank you! I’ve totally missed this new method in v1.13

$ iex
Erlang/OTP 25 [erts-13.2.2.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [jit:ns]

Interactive Elixir (1.15.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> previous_fun = Inspect.Opts.default_inspect_fun()
&Inspect.inspect/2
iex(2)> Inspect.Opts.default_inspect_fun(fn
...(2)>   value, opts ->
...(2)>     opts = Map.put(opts, :charlists, :as_lists)
...(2)>     previous_fun.(value, opts)
...(2)> end)
:ok
iex(3)> IO.inspect([?a, ?b])
[97, 98]
[97, 98]
1 Like

OT, but ideally, Elixir libraries would state which language version they were written for, so future versions of Elixir could do some on-the-fly transformation or at worst, emit a compiler error.

Could backticks, like in JavaScript’s template literal syntax, be used instead of a sigil? No technical reasons, just aesthetics. I find `charlist` cleaner than ~c”charlist”, it’s fewer characters too.

Then we end up with something like:
“” - binaries
‘’ - binaries OR deprecate to increase contrast between binary and charlist delimiters
`` - charlists