warren84
Destructuring a 3-tuple throws linter warning but still works. Incompatible types: tuple() !~ {var1, var2, var3}
I would like to know what I can do to get rid of the “incompatible types” warnings that are cluttering my phoenix server logs - I would willingly accept “operator error” as the cause if I could learn how to prevent the warnings. This is essentially the same as Destructuring a 2-tuple throws linter warning but still works. Incompatible types: tuple() !~ {var1, var2} - I am also using vscode and ElixirLS - in that post, one comment said that the problem would be fixed elixir 1.13 - I’m using 1.15. The phoenix app fine despite the warnings in the logs
Any help/direction is appreciated.
++++++++++++++++++++++++++
warning: incompatible types:
tuple() !~ {var1, var2, var3}
in expression:
# lib/dancePHX/dance_parser.ex:280
{ol, bts, d_bts} = acc
where “acc” was given the type tuple() in:
# lib/dancePHX/dance_parser.ex:278
elem(acc, 1)
where “acc” was given the type {var1, var2, var3} in:
# lib/dancePHX/dance_parser.ex:280
{ol, bts, d_bts} = acc
++++++++++++++++++++++++++
the code that’s generating this warning:
def _gen_phrases(el, acc) when elem(acc, 1) < 16 do <<<— line 278
[fig, b, _c] = el
{ol, bts, d_bts} = acc
...
end
There are also _gen_phrases(el, acc) functions using elem(acc, 1) == 16 and elem(acc, 1) > 16 which generate the same warning.
I’m using phoenix 1.6.11 and elixir 1.15.6.
++++++++++++++++++++++++++
$ elixir -v
Erlang/OTP 26 [erts-14.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
Elixir 1.15.6 (compiled with Erlang/OTP 26)
Most Liked
dimitarvp
Well, let me just say that I had no clue that function names could be prefixed with underscores.
03juan
I assume it’s warning that the basic tuple() type denotes tuples of any size and you’re matching it to a 3-element tuple, where it could fail.
A tuple in a pattern will match only tuples of the same size
— Patterns and Guards — Elixir v1.15.6
You could explicitly match the correct shape in the function definitions:
def _gen_phrases(el, {ol, bts, d_bts} = acc) when bts == 16
# or alternatively
# def _gen_phrases(el, {ol, bts = 16, d_bts} = acc)
def _gen_phrases(el, {ol, bts, d_bts} = acc) when bts < 16
def _gen_phrases(el, {ol, bts, d_bts} = acc) when bts > 16
# or leave out the guard as the other 2 clauses match everything <=16
christhekeele
Yep, they’re conventionally considered to be “hidden” (similar to double-underscore-prefixed struct fields) and will never be implicitly imported, auto-displayed in exdoc, or listed in iex helpers.
03juan
It was under our noses all along…
Function names may also start with an underscore. Such functions are never imported by default…
— Naming conventions — Elixir v1.16.3
It’s one of those things that we kinda learn about by practice and intuition, like every module’s __info__/1 or the venerable __MODULE__/0 and __ENV__/0, that we could actually apply to our own code but rarely do.
sodapopcan
Even more to the point __using__/1, __before_compile__/1, __after_compile__/2, etc!
EDIT: wait, no not more to the point! TIL __MODULE__/0 is a function ![]()
EDIT 2: wait… is it? I’m just going to shut up now, lol.







