DidactMacros
Understanding Elixir's Conversion of Blocks into Keyword Lists
In the context of iex…
…yields no error
IO.inspect :a do
5
end
#==> :a
…yields an error
:a do
5
end
error: syntax error before do
This question is in regards to the treatment of blocks in elixir, as I am trying to understand when they are automatically converted into kwlists.
Marked As Solved
zachallaun
They’re always converted to kw lists in contexts that allow kw lists. You can’t pass a kw list to the atom :a – it’s a syntax error.
For perhaps more clarity, the first example is equivalent to both of the following:
IO.inspect(:a, do: 5)
IO.inspect(:a, [{:do, 5}])
The :do is being passed as an option to the inspect function (and then ignored).
Also Liked
zachallaun
Here’s a handy guide on syntax sugar: Optional syntax sheet — Elixir v1.16.2
It’s definitely worth understanding. There’s surprisingly little of it!
DidactMacros
That cleared up everything, especially the added clarification. Which explains why the block was ignored (not outputted) by the inspect.
Just to clarify, the macro tag is because I wanted to know if this conversion takes place even when internal representation is taking precedent (such as when passed as an arg to a macro), but this seems to happen before all that.
DidactMacros
Thanks, was looking for something like this, but was searching under “blocks”.
More appreciation for the way the core team achieved elegance in elixir’s syntax.
sodapopcan
It also might be useful to think of it in “reverse” as it’s a little more accurate: The do syntax is actually sugar. It’s really more: “when can do stand in for a :do key in a kwlist” if that makes sense. The “truer” syntax—for lack of a better word—is def foo, do: "foo", or rather def foo, [{:do, "foo"}].
I actually have a bit of trouble myself grokking how the def family of macros work because otherwise Elixir is really very lispish—it’s just keyword lists all the way down.
defmodule(Foo, [{:do, def(bar, [{:do, "foo"}])}])
sodapopcan
I honestly don’t know! I haven’t never taken the time to fully understand at this level. defmacro defmacro calls define(:defmacro, ...) so AFAIK it’s the initial definition, at least in the Elixir part of Elixir’s source. Clearly there is something in the Erlang bits that are making that possible.







