Changes in the language since 1.6 or error in the book?

After having some experience with Elixir I decided to read “Programming Elixir 1.6” by Dave Thomas for the second time, this time very thoroughly. I noticed something strange for me on page 37 (chapter Variable Scope):

Elixir doesn’t really have blocks such as these, but it does have ways of grouping expressions together. The most common of these is the do block:

line_no = 50
if (line_no == 50) do
IO.puts “new-page\f”
line_no = 0
end

IO.puts line_no

However, Elixir thinks this is a risky way to write code. In particular, it’s easy to forget to initialize line_no outside the block, but to then rely on it having a value after the block. For that reason, you’ll see a warning:

$ elixir back_block.ex
warning: the variable “line_no” is unsafe as it has been set inside one of: case, cond, receive, if, and, or, &&, ||. Please explicitly return the variable value instead. Here’s an example:

case integer do
  1 → atom = :one
  2 → atom = :two
end

should be written as

atom =
case integer do
  1 → :one
  2 → :two
end

Unsafe variable found at:
T.ex:10

0

TL;DR: A variable is initialized in the outer scope of if, then inside the if block it’s rebinded to a new value and the binding propagates to the outer scope.

I was always under the impression that in such case a new inner scope is created and you can’t change the binding in the outer scoped, so the result would be 50, and not 0, as in the quoted book snippet.
Did something change in the language since 1.6 or am I missing something?

Yes, imperative assignment has been removed from the language in 1.8 or 1.7.

2 Likes

Good to know! Thank you @NobbZ !