massimo
I was recently made aware of a new programming language, the Roc language that is still in early development stage, but looks very interesting on many aspects, especially the fact that it took a lot of ideas from Elixir.
In particular it uses the <- operator as syntax sugar over async operations, for example
a <- File.read(filename)
is automatically tranlsated to
a = Task.async(fn -> File.reade(filename) end) |> Task.await()
and I was wondering if I could implement the same behaviour using Elixir macros.
Turns out it was easier than I thought.
I don’t know if anyone is going to ever find this useful, but here it is, in all its glory.
defmodule Roc do
defmacro a <- b do
quote do
retval = case unquote(b) do
t = %Task{} -> Task.await(t)
f when is_function(f) -> Task.async(f) |> Task.await()
_ -> raise ArgumentError, message: "parameter b must be a Task or a function"
end
var!(unquote(a)) = retval
end
end
end
and can be used this way
c <- Task.async(fn -> :return_value end)
d <- fn -> :function end
try do
_e <- 2
rescue
ex -> IO.inspect(ex)
end
IO.inspect({c, d})
# --- OUTPUTS
%ArgumentError{message: "parameter b must be a Task or a function"}
{:return_value, :function}
Trending in Discussions
A little off-topic, but I feel like people here have a good head on their shoulders.
I used to be quite good at making software. Was luc...
New
Hi there! :wave:
@frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
I’ve been using Emacs as my main code editor for more than a two years. It’s a custom build version although I’ve tried doom emacs and sp...
New
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with.
But I don’t use it anymore.
Serverless was the promis...
New
Lately I’ve been thinking about how to organize components as a LiveView application grows. One of the pain points I’ve found (for myself...
New
What IDE or editor are you using for Elixir development?
Personally, I use Zed, and I really like it, but sometimes I wish there were a ...
New
Other Trending Topics
Edit: 2026 May 15 - This post is archived.
Mob is alive!!
Main docs: mob v0.7.11 — Documentation
A bit of explanation for the slightly c...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
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
- #umbrella
- #full-time-contract
- #ai
- #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
- #metaprogramming










Showing Posts 3 to 1- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
massimo
Of course there’s no way that a 5 lines macro could replace the work being done on a compiler at the language level.
That wasn’t even the point.
As far as I understood what Roc does is “simply” avoid the callback hell, by ensuring that each call will wait until completion before the next one is started. The compiler can have a broader look on code at large, so has more information to optimize the calls, but what is doing is exactly “start and then await”, which is not bad per se. The calling process is blocked anyway when you await on something, in any language, or the order of the execution could not be guaranteed.
That doesn’t exclude that A is run concurrently with another computation somewhere else.
The indentation visible in the image you posted is used to scope the variables, every indentation in Roc creates a new scope (at least that was my understanding)
I don’t understand the error bubbling remarks: if the function being called return an error tuple, the error will be returned, if it raise an exception, the exception can be caught.
withgets a little help from the compilerAnyway, it was simply an exercise in metaprogramming to explore the possibility, I really thought it was not possible in Elixir, but I was wrong.
That’s why it’s posted in chat/discussions

al2o3cr
IMO this doesn’t quite capture the whole thing going on with
->; it’s missing the sequencing aspect of it.From the “A Taste of Roc” talk:
This is the desugared form of:
The presentation didn’t say it explicitly (at least not in the part I watched) but in addition to the above I assume Roc’s
awaitis also doing someResult-monad gyrations to ensure that error values bubble out, ala Elixir’swith.Note that starting a task and then immediately awaiting it in Elixir is kind of useless - the calling process is blocked while the Task executes and crashes if the task crashes. The “start then await” pattern is more of a Node idiom where
awaitis the way to hand control back to the runtime.dimitarvp
If you are interested in research in this area then you might also find the Alan language interesting.