Consider this example:
iex(1)> defmodule X do
...(1)> def f(), do: 1
...(1)> end
iex(2)> defmodule X.X do
...(2)> def f(), do: 1000
...(2)> end
iex(3)> x = 0
0
iex(4)> %{a: x, b: (x = 2; x), c: x}
%{a: 0, b: 2, c: 0}
iex(5)> x
2
iex(6)> X.f
1
iex(7)> %{a: X.f, b: (alias X.X; X.f), c: X.f}
%{a: 1, b: 1000, c: 1000}
iex(8)> X.f
1000
I understand that it’s useful to have variable contexts in map inherited from before-map context and then merged into one after-map contex.
But I don’t understand why alias context is transferred from left to right. I mean, it just makes no sense for me
This one will really bake your noodle 
iex(12)> x = 1
1
iex(13)> %{a: x, b: (x = 2; x), c: (x = x; x)}
%{a: 1, b: 2, c: 1}
iex(14)> x
1
I suspect the core difference is between runtime behavior (the assignments) and compile-time behavior (the aliases).
Yeah, I get the difference, but I do not get the decision behind this difference, and that’s what the question is about
bump, this question is important for me
alias is lexically scoped like bindings are, so I’m wondering if this might actually be a bug/unintended behaviour.
1 Like
require
, import
, and alias
All of the rules described so far apply to variable bindings. When it comes to one of these three special forms, their effect persists until the end of the do
block they are called in. Effectively, those forms see a slightly different scope division in which control flow constructs create a new lexical scope.
Scoping Rules in Elixir (and Erlang) — Elixir documentation
If you want to keep the current scope unaffected, wrap the evaluation in a function so the the effect is limited to the new scope.
iex> %{a: X.f, b: fn -> alias X.X; X.f end.(), c: X.f}
%{a: 1, b: 1000, c: 1}
iex> X.f
1
2 Likes
Thanks, I didn’t even know that this readthedocs documentation existed
I’d love to see this again in current documentation, as readthedocs is really old.