Why does the Elixir compiler show a warning for a variable in a list?

This is not really a problem as much as something that I found a bit baffling.

I found code similar to the following in an ExUnit test as a part of a Phoenix application:

strawberry = strawberry_fixture()   # creates a strawberry
assert [strawberry] = Garden.list_strawberries()

The interesting thing for me is that the Elixir compiler ocassionally displays a warning that the strawberry variable is unused. Does anyone know why that happens?

I hadn’t noticed that the assert had only one equals sign. Using == seems to solve this issue.

2 Likes

You have clearly found the solution to your actual problem but in an attempt to answer your question…

The “=” sign is a pattern matching operator, which as you allude to is not the same as equality comparison. The “strawberry” is being bound to a value in the fixture setup and then re-bound in the assertion through the pattern match but it is never read. The compiler warning is very useful in catching mistakes where you think you are matching but you actually are not. You can, as you found, fix this by changing to comparison. However if you do want to pattern match you can pin the value of “strawberry” in the pattern match so that it cannot be rebound using the pin operator “^” like so:

strawberry = strawberry_fixture()   # creates a strawberry
assert [^strawberry] = Garden.list_strawberries()

The pin operator can be used in any case where you want to do a pattern match that asserts the variables value be used as part of the match rather than allowing the variable name to be re-bound.

5 Likes

Thank you for the response. :slight_smile: It does seem to be due to the pattern matching but the warning was always about the variable on the first line. I assumed that it should be for the variable that gets assigned inside the list, but it was not the case. It is for sure due to the pattern matching though.

I always forget about the pin operator apart from when using Ecto queries. Thank you for reminding me. :slight_smile:

1 Like

The one on the first line is never read due to being clobbered on the second line. I’m not entirely sure exactly how it works deep down; my assumption is that on the second line the assert may use it or do enough to make the compiler think it is being used otherwise I would personally think two warnings would make more sense.

3 Likes

Ah, yes, that makes sense.