Unexpected behaviour for list subtraction operator (--)

I always thought of the -- operator as a subtraction operator for lists. With that in mind, I expected that, like - for numbers, it could be used repeatedly and each subsequent occurrence of the operator would take away more from whatever remained after the previous occurrence:

iex> [:a, :b, :c] -- [:a] -- [:b]
# I expected the result to be [:c] but in fact it was [:b, :c]

In order to accomplish my goal I had to add parentheses like this:

iex>([:a, :b, :c] -- [:a]) -- [:b]
# Result is [:c] as desired

Wondering if anyone can shed some light on this. Am I misunderstanding the role of --?

Thanks!

It’s the associativity, it’s opposite of what you expected, right to left instead of left to right. See: https://hexdocs.pm/elixir/master/operators.html

So a -- b -- c is really a -- (b -- c) instead of (a -- b) -- c

2 Likes

Ah I see. Thanks so much for the explanation and link. All makes sense now!

The ++ operator (list append) is also right associative which means that a ++ b ++ c is really a ++ (b ++ c). This is perfectly logical as it reduces copying.

2 Likes

Interesting, thanks for the background. So if you go right to left you can simply set the list on the right as the tail of the list on the left to efficiently concatenate while ordering the items in the expected way. Thanks!