Sanjibukai
Hello everybody,
I just noticed something that I admit I should have been notice way more earlier TBH..
Variables are scoped in ifs, conds, cases (and I bet it’s applicable to any block).
An example with a simplified snippet:
def doing_something do
a = 1
...
if some_true_condition do
a = 2
...
end
IO.inspect(a) # > Still 1 even if some_true_condition is true
end
Now I’m even surprised of how I didn’t got any bugs so far related to this behavior I wasn’t aware.
Maybe I’ve embraced FP well more than I think (so i’m glad).
But until now I didn’t come across (or maybe I didn’t notice) any resource explaining this behavior.
And it’s a really important behavior!
I searched on hexdocs.pm and looked on almost all the guides pages on elixir-lang and this is the only result I found, a changelog for version 1.3 where the following is stated:
Elixir will now warn if constructs like
if,caseand friends assign to a variable that is accessed in an outer scope.
And contrary to that there isn’t any warning anymore (on v1.10 btw).
I thought replacing the if construct by assigning from the whole block like so:
a =
if some_true_condition do
...
2
end
But in this case we are still changing the value with nil if some_true_condition is actually false instead of doing nothing.
If you happen to have to do something equivalent (changing a value in a block) how do you handle it?
Also if you have any more information about this behavior, I’m interested to learn more.
Thank you!
Trending in Discussions
Other Trending Topics
Chat & Discussions>Discussions
Latest on Elixir Forum
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










First 10 of 18 Posts
kokolegorille
It is more about scoping than FP…
I would do it like this if needed
lud
Remember that you are not changing the value of
a. What you are really doing is creating a new variable with the same name (and deleting the old variable).Sanjibukai
I meant, FP drastically reduced the usage of
ifs.I was more talking about changing a value or not.
Here with using
elseyou’ll still change the value…Or do you?
Indeed you can simply affect the variable to itself again:
So, yes this can do the trick.
Thank you for the link too BTW!
Sanjibukai
Indeed! My bad!
I should have say re-binding the variable..
lud
True, and with that in mind you clearly see that you cannot conditionally rebind it or not.
In the end, instead of
a = if ..., do: 2, else: other_valueYou will write the following
a = if ..., do: 2, else: aBut I’ve found this to be a very rare construct, generally hidden by a more complex one.
al2o3cr
FWIW, I find myself using this with
Ecto.Multiwhen operations should only be done sometimes:Sanjibukai
I my case it was also related to a use case with Ecto for a custom validation of a changeset.
Anyway, does anyone know why there is not anymore any warning as it was the case in Elixir 1.3?
NobbZ
Because in 1.7 or 1.8 the “imperative assignment”, which previously issued the warning and changed the value, got removed.
I do consider this a breaking change in elixir, others say the imperative assignment before was a bug that has been fixed with more than enough time of warning.
Sanjibukai
TIL that there was the “imperative assignment” in Elixir..
So if I correctly understood, now we have what’s a pattern matching, and a variable binding when a variable is on the left hand side (without the pin
^).. But back then there was an other behavior called “imperative assignment”?al2o3cr
There’s some nuance to Elixir scoping because what would be “reassignment” in other languages is really more of a “rebinding”:
The anonymous function in
thingcaptures the value offoowhen it’s initially evaluated in the second expression. Subsequent “reassignment” offoois really rebinding the name, so the anonymous function retains its original reference.This behavior is intended to be more ergonomic than Erlang, which uses the pattern-matching approach and allows exactly one assignment / binding for a name. In that style, the example above is:
Written in this style, it’s much more apparent that the second assignment shouldn’t affect the first binding.