Nicd
I am getting odd warnings about pattern matching when compiling the following code (it is from a Phoenix controller, but as the warning doesn’t have anything to do with Phoenix, I posted this in the generic questions section):
# Edit case for editing user's password
def do_edit(conn, %{
"user" =>
%{
"type" => "password",
"old_password" => old_password,
"password" => _
} = params
}) do
user = AuthUtils.get_current_user(conn)
password_changeset = User.password_changeset(user, params)
with {:old_pass, true} <- {:old_pass, AuthUtils.check_user_password(user, old_password)},
{:updated, %User{}} <- {:updated, AuthUtils.update_user(password_changeset)} do
conn
|> put_flash(:success, "Password changed.")
|> redirect(to: Routes.preferences_path(conn, :edit))
else
err ->
error_changeset =
case err do
{:old_pass, false} ->
# We need to add an action to the changeset so that Phoenix will display the error,
# otherwise it will think the changeset was not processed (as it has not been passed
# to any Repo call) and will not show the errors
%{password_changeset | action: :update}
|> Ecto.Changeset.add_error(:old_password, "does not match your current password")
{:updated, cset} ->
cset
end
conn
|> common_edit_assigns()
|> put_flash(:error, "Error changing password.")
|> render("preferences.html", pass_changeset: error_changeset)
end
end
The case statement inside the with’s else block gets the following warnings:
warning: this clause cannot match because of different types/sizes
lib/code_stats_web/controllers/preferences_controller.ex:67
warning: this clause cannot match because of different types/sizes
lib/code_stats_web/controllers/preferences_controller.ex:74
The lines refer to the {:old_pass, false} -> and {:updated, cset} ->. But I know that they do match and the code works. The function AuthUtils.check_user_password/2 returns a boolean, and AuthUtils.update_user/1 returns either a User struct or a changeset.
If I hover over the clauses in VSCode, it tells me that the first clause can never match {:updated, <changeset>} and the second clause can never match {:old_pass, false}, but that makes no sense to me (as the opposite clauses match those!).
Now to be clear, I’m not looking for advice how to structure the code better. I am simply wondering why the warnings are given. I cannot see the problem in the match.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #ai
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #security
- #hex










Showing Posts 1 to 4- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
OvermindDL1
That’s one of those
withbugs, I get a LOT of those warnings, so many that I’ve ended up stripping out almost all ofwithfrom my project and going back to other libraries and patterns because of that as well as two other annoying issues I have with it. There is a still-open github issue about it at:https://github.com/elixir-lang/elixir/issues/6738
pedromvieira
Is there any extra benefits to use with syntax? IMHO it’s just hard to read compared with regular syntax.
Nicd
In this case it is not so easy to read because I haven’t refactored it into a nicer format yet. But sometimes you need to do many things in succession and handle all of their failures. Then with helps you to avoid a pyramid of nested conditionals. I know my code is not the best example but here is one with that has more things going on:
Here you can see the happy path is easily readable and the error handling is after it, and there is no nesting.
OvermindDL1
Just as an example, the alternative to that with in pure elixir itself (I still prefer a few specific libraries like
okandexceptional):Again, the happy path is easily readable and the error handling is after it with no nesting. In addition this will cause no odd match warnings when compiling.
This is one example of why I find the current
withimplementation improperly designed. It should have been something like:Which would allow you to even add in
rescue/catch/afterclauses as well, plus it doesn’t have those weird,droppings at the end of the expressions and it follows the rest of the Elixir language’s form (excepting the also weirdforin the same way). Thewithsyntax was put in with relatively little discussion and resolution of issues so it really stands out as an oddity… >.>