If you could change one thing in Elixir language, what you would change?

If you could change one thing in Elixir language, what you would change?

Get rid of alignment in the formatter, in favour of indentation-only (I can’t even stand using the formatter anymore because of this).

1 Like

Well make the change in freedom_formatter. ^.^

1 Like

I usually make my rebindable variables end in ! And I have credo check that for me.

2 Likes

One thing more that would like to change is that - You should not successfully pattern match empty map with any other maps.

%{} = %{abc: "something"} # This should fail, but it is not.
# %{abc: "something"}

a = %{abc: "something"}
case a do
%{} -> "this" # This should not be matched, but this one is matched.
%{abc: _} -> "that"
# "this"
1 Like

If Elixir had static typing it would be the “perfect” language for me.

6 Likes

Ha! Was just going to write that! :smiley:

My main grieve is Elixirs refactorability. It is not bad but it also does not spark joy :slight_smile:

2 Likes

That both your cases match is logical and consistent as there is only one type of matching irrespective of whether it is with a =, case or any place where matching occurs. It is really not illogical that it does match as a map in any a pattern means check that it is a map and has at least the key/values specified. Otherwise you would end up with

%{abc: "bert"} = %{abc: "bert", xyz: "carl"}

failing as not all the keys are specified. Which would make the matching almost useless.

8 Likes

Only solution I can think of (but I find it un-Erlangy) is to have “special” syntax for such matches, like:

%{...} = %{abc: "bert"}
%{abc: "bert", ...} = %{abc: "bert", xyz: "carl"}
2 Likes

There is one simple change that should not (in principle) break any existing code, but which can spare inexperienced developers a lot of frustration:

Let structs: false be the default option for inspect/2.

Setting ‘structs’ to either true or false is trivial. Being aware of its existence and recalling it from memory in the middle of a debugging frenzy is not. I had to automate the output of the inspect/2 function (using a keyboard shortcut) simply so that I do not, ever again, forget to set ‘structs’ to false. Opting out of unnecessary detail makes more sense than opting in to access potentially valuable information.

We could say the same about charlists: :as_lists, but on the other hand it also can become confusing in stack traces that use charlists and/or structs.

Yeah this is what I wish Erlang and Elixir both did.

I’m really curios to learn examples where this was useful to you. To me, I much prefer the compact representation but it’s subjective.

Also, worth clarifying, the issue is not just showing structs as underlying maps, its more about NOT using custom inspect implementation for structs, correct?

3 Likes

Take the example of a changeset on which Ecto.Changeset.get_field/3 is applied: the value may be taken from ‘changes’, or from the data struct. When [structs: true], the first one is visible, the second one hidden. This is not an issue at all when you are experienced. At the beginning, however, you miss the fact that there is a struct holed in there. You receive a clue, but it is not enough to guide you. Because, unlike the (also baffling) charlists mentioned by hauleth, that clue is lost amongst a heap of other information.

I hope the above sheds enough light on the issue. Basically, for experienced users, another version of inspect/2, named in a way that would relinquish all claims to in-depth inspection (say glance/1 or peek/1), could provide the compact representation most developers likely prefer.

The problem with structs: false by default is that it returns “raw” representation of struct, so if you will have:

defmodule Foo do
  @enforce_keys [:a]
  defstruct [:a]
end

%Foo{a: 1} |> inspect(structs: false)
# => %{__struct__: Foo, a: 1}

## And now is a problem

%Foo{} # This will fail as not all required keys are present
%{__struct__: Foo} # This will happily pass with invalid structure

Oh, if I wasn’t working on so many other projects, I would.

1 Like

I like that. Seems more useful

If we just want to know if something is a map we can use Kernel.is_map/1

1 Like

I don’t know if it was already said but replacing the arrow <- with in for the comprehension syntax.

This bothers me even more because of the existing of the in keyword for lists
 ¯_(ツ)_/¯

1 Like

There is problem:

primes = [2,3,5,7,9]

for a <- 1..10,
     a in primes,
     do: a * 3

Is completely valid and will filter out non-prime a. So this would make useful feature impossible.

2 Likes

I mean, this is not as if Enum.member? didn’t exist

We are used to write in for iteration in many languages

And precisely use predicate (with question mark) methods for return a boolean

Maybe using in? in the case you illustrated

I bet that currently in is a syntactic sugar anyway


You should see some Erlang code to understand arrows have a special meaning.

Although it looks like Ruby, it comes from Erlang
 Elixir has made a bridge for Ruby programmers to get into Erlang, but Erlang comprehension looks like this.

[X || X <- [1,2,a,3,4,b,5,6], integer(X), X > 3].
1 Like