I will post the same answer from before: I like the explicitness of pattern
matching. In Elixir, as soon as I see ^foo, I know I am matching. If there is
no ^, I know the previous value regardless if it there is one or not, will be
discarded. If pattern matching is not explicit, I always need to know if a
variable was previously defined or not to know what is going to happen. To me
this behaviour is non negotiable. In my experience, it is more likely to run
into accidental matches than into accidental rebindings.
Another possible limitation to the suggestion above can be related to macros.
Let's suppose you have a macro that stores a value in a hygienic variable:
defmacro do_something(a, b) do
quote do
var!(hello, Hygienic) = calculate_something(unquote(a), unquote(b))
end
end
Someone may call this macro multiple times but we always care about the last
value
of hello. If we make a distinction in between being assigned once and then
multiple times, the macro simply won't work. Or the macro developer would need to
work around this behaviour by inspecting the environment or we would need to
provide some sort of functionality that does it for you. Maybe this behaviour
could be built-in in var! or maybe we'd need to introduce something like:
defmacro do_something(a, b) do
quote do
set!(hello, Hygienic) = calculate_something(unquote(a), unquote(b))
end
end
We can see how this is getting complex:
1. Use = to define variables
2. Use ^ for pattern matching
3. Use := for rebinding
4. Use set! in macros when you don't care if a variable was previously defined or not
It is also interesting to point out that the := operator won't work for rebinding
inside clauses. For example, how would you make the rebinding below explicit?
x = true
case false do
x -> :ok
end
Of course, there are interesting consequences for making a distinction in between
defining and rebinding a variable by introducing something like the := operator.
We could have better control of the scope to provide better warnings or even make
it easier to implement imperative for loops:
x = 0
for i <- 1..5 do
x := x + i
end
x #=> 15
But the fact Elixir have different ways for variables to be introduced in the
scope, adding more rules can make the overall system very complex.
Not allowing rebinding does provide a little bit of encouragement towards factoring things better, but I have seen manys a `X1` `X2` in my time :(