Sanjibukai
About variables scope
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!
Most Liked
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).
benwilson512
What you’re proving is precisely that rebinding isn’t mutability. The function closes over the value of x. That value isn’t changed when you rebind x. If it changed in the function then x is in fact not immutable. Javascript does not have immutability, so it behaves the way you observe. Closures in immutable languages behave the way you observed in Elixir.
al2o3cr
FWIW, I find myself using this with Ecto.Multi when operations should only be done sometimes:
multi =
Ecto.Multi.new()
|> Ecto.Multi.insert(:a, some_changeset)
|> Ecto.Multi.update(:b, some_other_changeset)
multi =
if control_variable do
Ecto.Multi.insert(multi, :c, optional_changeset)
else
multi
end
Last Post!
LostKobrakai
cond do
to_date_time(string) = datatime -> datetime
to_date(string) = date -> to_date_time("#{string}T00:00:00+03:00")
String.contains?(string, "+") -> to_date_time(String.replace(string, "+", "T00:00:00.000+"))
true -> string
end
Popular in Discussions
Other popular topics
Chat & Discussions>Discussions
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
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security









