Reputation: 6222
I saw this code at the Elixir School:
with {:ok, user} <- Repo.insert(changeset),
{:ok, token, full_claims} <- Guardian.encode_and_sign(user, :token, claims) do
important_stuff(token, full_claims)
end
I don't get the difference to simply:
{:ok, user} <- Repo.insert(changeset),
{:ok, token, full_claims} <- Guardian.encode_and_sign(user, :token, claims)
important_stuff(token, full_claims)
Upvotes: 0
Views: 52
Reputation: 121010
{:ok, user} <- Repo.insert(changeset)
without with
would raise (CompileError) undefined function <-/2
in the first place. You probably meant {:ok, user} = Repo.insert(changeset)
.
Kernel.SpecialForms.with/1
plays the role of Either monad to some extent.
If RHO matches to LHO, it goes to the next clause. Otherwise, it immediately early returns the non-matched RHO, discarding all the other clauses. Consider several functions that should be applied sequentially, if and nobly if the previous one succeeds. Somewhat along these lines.
with {:ok, text} <- File.read(name),
{:ok, words} <- MyStemmer.get_words(text),
count when in_integer(count) <- Enum.count(words),
do: IO.puts("File contained #{count}" words)
If there is no such file, the whole snippet would return {:error, :enoent}
because the very first clause would fail to pattern match LHO.
{:ok, text} = File.read(name)
would instead raise MatchError
when there is no such file.
I have written a blog post on the subject three years ago, it might be still worth reading.
Upvotes: 3