How to fix/suppress this warning? (How to compare structs?)

I’m trying to implement the ok_content/1 function as used in this presentation: ElixirConf 2020 - Brian Marick - Tricks and tools for writing Elixir tests - YouTube

My code is:

def ok_content({state, content}, struct) when is_struct(struct) do
  assert struct = content
  ok_content({state, content})
end
def ok_content({state, content}) do
  assert state == :ok
  content
end

But I get the warning: ‘variable “struct” is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)’

I tried the pin operator, but that seems to pin all the variables inside the struct as well, so it won’t work. The code seems to work, despite the warning, but I’m triggered by warnings and can’t leave them in the code…

try:

assert struct == content

or:

^struct = content

= is the matching operator, which will rebind struct.

Both seem to fail.

I would like to do for example

ok_content({:ok, %Dog{age: 5}, %Dog{})

But if I do ^struct = content or struct == content, the comparison fails as the content struct isn’t empty.

Assert struct = content works, but gives the warning.

That’s because it always passes. What exactly are you testing for?

^struct = content

doesn’t work because, as you noticed, the match operator can’t perform a partial match when the left-side term
is a pinned variable. In this chase, it checks whether struct is exactly equal to content, which is probably not what you want.

I assume you want to check whether content is of type struct?

Then I suspect your only option is to do it statically with:

assert %MyStruct{} = content

Interesting. Apparently you can pattern match to the struct type.

So

%struct_type{} = %Dog{}

gets you the type and you can assert the type that way. Cool.

2 Likes