Just a curiosity with ranges 1..2 in Elixir and greater than

So I was playing around with Elixir in a sandbox at work and I came across this

if 1…20 > 8 do
IO.puts(‘Alert’)
end
prints Alert ?

if 1…20 > 1…50 do
IO.puts(‘Alert’)
end
doesn’t print

if 1…20 > 1…10 do
IO.puts(‘Alert’)
end
Prints Alert

Anyone know why this happens, Just curious how the comparison works in elixir, with ranges, numeric etc. What are ranges considered etc.

According to

this is handled by erlang.>

My first guess would be, that the range is made into a list of elements [1,2,3,…] and the > compare the length of the list with the other side. I will take a longer look into now. :smiley:

Edit 1: Part of the answer seems to be that erlang defines number as always smaller than lists
http://erlang.org/doc/reference_manual/expressions.html#term-comparisons

The arguments can be of different data types. The following order is defined:
number < atom < reference < fun < port < pid < tuple < map < nil < list < bit string

Edit 2:
Ah okay,
and the third of our examples would be explained by that fact, that lists are compare element for element. So after 10 comparision you compare a not-empty list with an empty one, resulting in an empty list being “less” than the not empty one.

Same source, next line

nil in the previous expression represents the empty list (), which is regarded as a separate type from list/0. That is why nil < list.

Edit 3:
As @LostKobrakai notes, it’s map, not a list. Still wondering how these are compared. Value by value, maybe?

1 Like

The other part is that ranges are stored as a struct, which by itself is a map. And maps are always greater than numbers.

6 Likes

As @LostKobrakai notes, the range 1..10 is actually %Range{first: 1, last: 10} under the covers.

1 Like

Worth mentioning that if you try to compare range literals on recent Elixir versions you’ll get a warning:

iex(1)> 1..20 > 1..10
warning: invalid comparison with struct literal 1..20. Comparison operators (>, <, >=, <=) perform structural and not semantic comparison. Comparing with a struct literal is unlikely to give a meaningful result. Modules typically define a compare/2 function that can be used for semantic comparison
  iex:1

true
5 Likes

Thanks all, that explains a lot, was randomly curious about this. Answered all of my questions.