Yea, I'm mostly approaching this from the point of view of learning any new language is climbing a learning curve. If you are coming from most of the mainstream languages (java, javascript, python, etc) you are going to want to rebind things because that's how imperative languages roll.
This is probably colored from my own experience of going from Python (mainly) to Elixir (mainly). As a toy example, imagine having to remove all the negative numbers from a list in the middle of a function.
Most python programmers would reach for a list comprehension after learning about list comprehensions (which is great because they are more FP)
my_list = [number for number in my_list if number >= 0]
So you pick up Elixir and you are trying to do the equivalent thing after reading through the docs
my_list = for number <- my_list, number >= 0, do: number
And that works fine, it's my_list is exactly what you expect, no negative numbers.
Let's try the same thing in Erlang
MyList = [X || X <- MyList, X >= 0].
** exception error: no match of right hand side value
As a new user coming to the language, trying to do something so simple and getting a somewhat opaque error message is a significant degree of friction.
I have found that when I want the old value of a variable to no longer be available rebinding the name is a great way to ensure that. If in the future I decide that I need the old value later on in the function I can always just change the bind to some other name easily enough, but it prevents me from using state when I meant to use updated_state.
Not to say one way is better than the other, I just found this use of rebinding to work well for me by making it "impossible" to use the old / stale / out-of-date value.
I'm on the fence about re-binding variables. I don't really mind it and have gotten used to the pin operator when I need it. I actually use variable re-binding quite a bit but always only in situations where I want a prime.
def foo(bar) do
bar = decorate(bar)
{:ok, bar}
end
I like that better than calling it something like `new_bar`. I kind of wish there was prime syntax along the lines of `bar' = decorate(bar)` but I can deal with re-binding when only used like this (and really, the stakes are low). More complex cases can generally always be handled with piping.
my preference is to only use rebinding if I need to rename something more than once (can happen, in with blocks), and when I do it I postfix-sigil with ! as a code annotation to remind myself to watch out when refactoring the code.
def foo(bar!) do
bar! = decorate(bar!)
bar! = some_more(bar!)
{:ok, bar!}
end
Ha! That's a new use of `!` I haven't seen :) But I suppose we are saying completely opposite things. I use rebinding only when I re-bind once. In your example, I would use pipes with a single re-bind:
def foo(bar) do
bar =
bar
|> decorate()
|> some_more()
{:ok, bar}
end
Ah ok, I see! I didn't think of this situation. I'm pretty new to the language and only have done hobby projects so I haven't run into this specific scenario. I think here I would just use different names, even if ugly. To me the only "danger" is just in getting confused about what is what. There is otherwise no danger from a memory standpoint since Elixir is immutable. But I can appreciate your use of it here. [edited to add a missing word]
This is probably colored from my own experience of going from Python (mainly) to Elixir (mainly). As a toy example, imagine having to remove all the negative numbers from a list in the middle of a function.
Most python programmers would reach for a list comprehension after learning about list comprehensions (which is great because they are more FP)
So you pick up Elixir and you are trying to do the equivalent thing after reading through the docs And that works fine, it's my_list is exactly what you expect, no negative numbers.Let's try the same thing in Erlang
As a new user coming to the language, trying to do something so simple and getting a somewhat opaque error message is a significant degree of friction.I have found that when I want the old value of a variable to no longer be available rebinding the name is a great way to ensure that. If in the future I decide that I need the old value later on in the function I can always just change the bind to some other name easily enough, but it prevents me from using state when I meant to use updated_state.
Not to say one way is better than the other, I just found this use of rebinding to work well for me by making it "impossible" to use the old / stale / out-of-date value.