matreyes

matreyes

What do you think of AsyncWith?

Today I’ve discovered AsyncWith https://github.com/fertapric/async_with, and I was pretty amazed.
I can think in many use cases where this is very useful.

You can do something like this:

use AsyncWith

opts = %{width: 10, height: 15}
async with {:ok, width} <- Map.fetch(opts, :width)
           {:ok, height} <- Map.fetch(opts, :height) do
   {:ok, width * height}
end

All clauses run on async tasks, returning when they are all resolved.

So what does the community think? do you have a more “elixier” way to do this?

Most Liked

mgwidmann

mgwidmann

What exactly happens when you have sequential clauses? And if you had 2 non-sequential followed by 2 clauses dependent upon those? It seems its just syntactic sugar for doing something like:

with pid1 <- Task.start(fn -> long_running_task() end),
     pid2 <- Task.start(fn -> long_running_task2() end),
     {:ok, data1} <- Task.await(pid1),
     {:ok, data2} <- Task.await(pid2) do
  {:ok, data1, data2}
else
  {:error, n} ->
    {:error, n}
end

IMHO I’d just prefer to see the tasks being spawned rather than using this library. It seems like its an attempt to implement JavaScript’s async keyword when Elixir already handles asynchronous communication much better than JavaScript does.

matreyes

matreyes

Tasks are spawned as soon as all the tasks that it depends on are resolved, so you can do something like this:

def show(conn, %{"id" => id}) do
   async with {:ok, post} <- Blog.get_post(id),
            {:ok, author} <- Users.get_user(post.author_id),
            {:ok, posts_by_the_same_author} <- Blog.get_posts(author),
            {:ok, similar_posts} <- Blog.get_similar_posts(post),
            {:ok, comments} <- Blog.list_comments(post),
            {:ok, comments} <- Blog.preload(comments, :author) do
    conn
    |> assign(:post, post)
    |> assign(:author, author)
    |> assign(:posts_by_the_same_author, posts_by_the_same_author)
    |> assign(:similar_posts, similar_posts)
    |> assign(:comments, comments)
    |> render("show.html")
  end
end

Of course you can do it with Task.start |> Task.await if you sort them correctly, but it seems like a really cool syntactic sugar.

Ankhers

Ankhers

I think it depends on what you are doing in the with. In that specific case of Map.fetch/2, it will probably take longer with the overhead of spawning additional processes. However, I could potentially see this as being useful if you have longer running clauses.

With that said, you should be careful when using something like this. It is possible that you actually want all of the previous clauses to run before running the following. Even if it doesn’t rely on the result of the previous (I’m sorry if that doesn’t make sense).

A question for anyone that knows about this library. If multiple clauses fail, which value gets returned?

Where Next?

Popular in Discussions Top

New
mmport80
I have put far too much effort into Dialyzer over the last year or so - and basically - I doubt it’s worth the effort. It’s not as easy ...
New
fireproofsocks
This is more of a general question, but I’m wondering how other people in the community think about the pattern matching in function sign...
New
WildYorkies
It seems that the more I read, the more I find Elixir users speaking about all the ways that Elixir is not good for x, y, and z use cases...
New
marciol
Please, let me know if this kind of discussion already took place in another topic . Hi all, how do you consider if is better to build ...
New
PragTob
Hey everyone, this has been brewing in my head some time and it came up again while reading Adopting Elixir. GenServers, supervisors et...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
hazardfn
I suppose this question is effectively hackney vs. ibrowse but we are at a point in our project where we have to make a choice between th...
New
acrolink
How does the two languages compare when it comes to server side application development? Any experiences or ideas? Thank you.
New
wmnnd
The Go vs Elixir thread got me thinking: Would it be too hard to implement a simple mechanism for creating Go-style static app binaries f...
New

Other popular topics Top

AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement