Yes they are the same. A do block after a call adds the [do: ...] argument to the function/macro call on the left.
So if you call this (notice the parentheses for the if call)
if(a == 1) do
:ok
end
The compiler kind of rewrites it to if(a == 1, [do: :ok])
This works for functions too:
defmodule Test do
def myfun(value, block) do
value |> IO.inspect(label: "value")
block |> IO.inspect(label: "block")
end
end
Test.myfun :some_value do
a = 1
b = 2
a + b
end
This will output the following:
value: :some_value
block: [do: 3]
But as myfun/2 is a function and not a macro, the block is evaluated before being passed to the function, hence you see [do: 3], whereas with macros the quoted block is passed. This syntactic sugar is then less useful for functions.
The for macro is special, because if you pass into: %{}, do: stuff(), the do and into are in the same keyword list ; if you pass into: %{} and then a do end block, the compiler will add another argument to the for() call, containing just the do block:
iex(1)> quote do
...(1)> for a <- 1..2, into: %{} do
...(1)> {a, a*a}
...(1)> end
...(1)> end
{:for, [],
[
{:<-, [],
[{:a, [], Elixir}, {:.., [context: Elixir, import: Kernel], [1, 2]}]},
[into: {:%{}, [], []}],
[
do: {{:a, [], Elixir},
{:*, [context: Elixir, import: Kernel],
[{:a, [], Elixir}, {:a, [], Elixir}]}}
]
]}
iex(2)> quote do
...(2)> for a <- 1..2, into: %{}, do: {a, a*a}
...(2)> end
{:for, [],
[
{:<-, [],
[{:a, [], Elixir}, {:.., [context: Elixir, import: Kernel], [1, 2]}]},
[
into: {:%{}, [], []},
do: {{:a, [], Elixir},
{:*, [context: Elixir, import: Kernel],
[{:a, [], Elixir}, {:a, [], Elixir}]}}
]
]}
I guess that is why for is defined in Kernel.SpecialForms as an error because it is handled at the compiler level.


















