Checking if an enum is empty - Credo vs Compiler

Credo is smart enough to check for (something like) this:

assert length(the_list) == 0

with this response:

Checking if an enum is empty should be done by using
Enum.empty?(enum)
or
list == []

My question is, why isn’t the compiler smart enough to fix it “under the hood”? Seems odd.
I believe Scala does exactly that.

Its not the compilers task to lint your code. This has nothing to do with “smartness”, its just a matter of responsibilities.

The expressions length(list) == 0 and list == [] have slightly different behaviour when the variable list isn’t actually a proper list:

  • length(list) will fail if the input is not a proper list and this means that the whole clause will fail - even it might seem it would succeed otherwise - e.g. length(value) >= 0 used as a guard would fail for input [1 | 2].
  • list == [] will just return false for anything that is not an empty list.

Because of this difference, such a conversion is not safe to be performed automatically by the compiler - it’s extremely hard to prove it would be safe. A compiler has to be 100% sure an optimisation is safe to perform it. On the other hand, in 99% of cases it actually is safe and the programmer can switch it.

6 Likes

Thanks for the response, I hadn’t considered improper lists.

The problem, however, as I see it is that if I do (somehow) have an improper list:

foo = [1 | 2]

and I run the following checks:

is_list(foo)
Enum.empty?(foo)

I come to the incorrect conclusion that I have a list with one or more items.
Performance implications aside, it almost seems better/preferable to do length(foo) == 0, because at least that blows up with an argument error. Neither of the Credo suggestions do.

1 Like

Improper lists are still lists, this isn’t an incorrect conclusion. If you want to make sure something is a proper list, do a dedicated check for that. If you want to know if a list is non empty, checking equality with [] is the clearest thing to do.

1 Like

RE: “… checking equality with [] is the clearest thing to do.” I could have just as easily said foo = [] instead of Enum.empty?(foo) in my example. As Credo recommends either, they need to be functionally equivalent.

RE: “If you want to make sure something is a proper list, do a dedicated check for that.”
How do you check for an improper list? (i.e. differentiate [1 | 2] from [1 | [2, 3]])

https://hexdocs.pm/elixir/List.html?#improper?/1

It’s nearly never worth doing this check though.