I’m following this tutorial on authenticating a user when they log in/out, in phoenix. It requires that I create in my Guardian implementation module the authenticate function with different arities, corresponding to different scenarios. This is the part that is failing:
def authenticate(%User{} = user, password) do
authenticate(
user,
password,
Argon2.verify_pass(password, user.encrypted_password)
)
end
defp authenticate(nil, password) do
authenticate(nil, password, Argon2.no_user_verify())
end
defp authenticate(user, _password, true) do
{:ok, user}
end
defp authenticate(_account, _password, false) do
{:error, :invalid_credentials}
end
This fails with the following error:
** (CompileError) lib/myapp_web/authentication.ex:44: defp authenticate/2 already defined as def in lib/myapp_web/authentication.ex:36
lib/myapp_web/authentication.ex:44: (module)
I am using elixir 1.14.1, Erlang 25, with phoenix 1.6, guardian 2.3, ueberauth 0.10.3
Could it be because the first clause uses def and defines a public function authenticate /2 while the next 2 clauses use defp and define a private function authenticate/2? You are basically trying to define 2 functions with the same and arity which is illegal.
Functions in the same module, with the same name and same arity may have multiple versions of the same function that differ in the pattern of parameters. These versions must all be either ‘def’ or ‘defp’ but cannot mix. Either all clauses of a function need to be public or they all need to be private.
Multiple function heads with the same arity are technically the same function. In fact they get rewritten to a case under the hood. So it wouldn’t make sense for a function to be both private and public.
Just to be picky but saying that there are different versions is really weird and a bit bonkers. There is only 1 function with multiple clauses and not different versions because you can’t have multiple versions of a function. Having the multiple def does not really make it clearer.