Hello,
Is there a one liner option to get a tuple from a function and return it directly ?
Example of 2 lines :
{:ok, book} = get_book(opts)
{:ok, book}
is there a way to return it directly ?
Thanks
Hello,
Is there a one liner option to get a tuple from a function and return it directly ?
Example of 2 lines :
{:ok, book} = get_book(opts)
{:ok, book}
is there a way to return it directly ?
Thanks
is enough since the tuple is the value of the fuction call. But maybe I misunderstood your question.
{:ok, book} = get_book(opts); book
You might also look for ! function… like get_book!()
or maybe I don’t get it…
because it could be a one liner too…
get_book(opts)
I am not sure I understood your question, but you don’t need to match the tuple if you just want to return it. This works:
# This function returns the tuple
def my_function do
# …
get_book(opts)
end
This code is not equivalent to the one in the original question, though.
The original one raises on e. g. {:error, :foo}
, yours propagates it further.
{:ok, book} = get_book(opts)
is the expression. Everything is an expression in Elixir. That said, you might just omit the second line.
def foo(opts) do
{:ok, _} = get_book(opts)
end
The above would both â‘ raise if get_book/1
returned something unexpected and ② return the result of the match expression if there was a successful match.
@mudasobwa and if it was in a “widh” statement" ? We must have that line to return the tuple ?
with {:ok, book} <- get_book(opts) do
{:ok, book}
else
{:error, _error} ->
raise InvalidRequest
end
You can invert the with
, i.e. match on and handle the error in the body. That will just return the ok result silently.
Be careful of sacrificing readability in the quest for less lines.
Or just use case
here. Much cleaner.
Generally speaking, one should not use with/1
statement with a single match and else
clause (credo
would even warn about this.)
Inverting a clause to avoid else
as suggested by @cmo suffers from the same disease as just returning get_book(opts)
result directly: it won’t raise if get_book/1
returned somewhat weird. Usually, we use case/2
for that kind of behaviour.
opts
|> get_book()
|> case do
{:ok, _} = result -> result
{:error, _error} -> raise InvalidRequest
end
with {:error, _error} <- get_book(opts) do
raise InvalidRequest
end
This is the closest I could get to it being a 1 liner and having mostly the same functionality. The one difference is that it produces a different error.
opts |> get_book() |> then(fn {:ok, x} -> x end)
If you know you’ll never get an error, you could also do this:
opts |> get_book() |> elem(1)
I’d probably avoid using these in most situations though. In other languages with the result monad, they often have a function called unwrap, which will extract the value or raise an exception if the value is an error. I’d probably just define my own if I was doing this commonly, but there are a number of monadic libraries in Elixir that do something similar.
One more, here are some syntactic tricks to turn it into 1 line, though probably not what you’re looking for.
({:ok, _x} = get_books(opts)) |> elem(1)