A lot of confusion in the previous docs was caused by
trying to explain both bracket-based and dot-based
syntaxes in the same place. This made sense at the time
because those syntaxes were not described elsewhere.
But now we can link to other resources and focus the
docs specifically in the Access module.
Elixir's with is expanded into a series of nested cases. For
example, this code:
with {:ok, a} <- fun_a(),
{:ok, b} <- fun_b() do
wa = fun_w(a)
wb = fun_w(b)
else
error -> {:c, error}
end
would be expanded to something similar to this:
case fun_a() do
{:ok, a} ->
case fun_b() do
{:ok, b} ->
wa = fun_w(a)
wb = fun_w(b)
var1 ->
case var1 do
error -> {:c, error}
var2 -> error({with_clause, var2})
end
end
var1 ->
case var1 do
error -> {:c, error}
var2 -> error({with_clause, var2})
end
end
The generated code can be optimized for else clauses that
only contain a single catch-all clause (a variable that would
bind everything). Applying this optimization, the code of the
example above would be:
case fun_a() do
{:ok, a} ->
case fun_b() do
{:ok, b} ->
wa = fun_w(a)
wb = fun_w(b)
error ->
{:c, error}
end
error ->
{:c, error}
end
The usage of items and elements was mixed,
but Erlang refers to them as Elements,
and Enumerable also refer to them as elements,
so I took the liberty to standardize its usage.
Defining __MODULE__.Something in a nested defmodule would fail
to compile. This commit address this:
defmodule Foo do
defmodule __MODULE__.Bar do
__MODULE__ == Elixir.Foo.Bar
end
end
Since `__MODULE__` expands to a fully qualified name `Elixir.Foo`,
the nested module must then be `Elixir.Foo.Bar`. This commit also
fixes an alias leakage that would happen under such scenarios.
Another possible interpretation would be for it to return `Foo.Foo.Bar`.
However, that would mean we would not be able to access the module
right below its definition using `__MODULE__.Bar`, which means its
`Foo.Foo.Bar` would be the incorrect choice.