5 ms·
Speaking for myseld, rebinding variables in Elixir is my least favorite part of the language, and I specifically avoid using the feature.
by PopeDotNinja 6y ago
Speaking for myseld, rebinding variables in Elixir is my least favorite part of the language, and I specifically avoid using the feature.
- ihumanable 6y agoYea, 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.
- dnautics 6y agoyou shouldn't do it in your code, and code linters (well, credo) can check for it and yell at you. I think you might have to activate it currently. I 100% guarantee you don't miss "immutable variables" in your REPL. Pid = module:start_link(...). oh crap. start_link/n returns {:ok, _}, not naked pid. {ok, PidForRealThisTime} = Pid.
- sodapopcan 6y agoI'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.
- dnautics 6y agomy 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
- sodapopcan 6y agoHa! 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
- dnautics 6y agowell, I guess I gave a poor example, suppose you needed to destructure that bar! out of an ok tuple. def foo(bar!) do with {:ok, bar!} <- thing1(bar!), {:ok, bar!} <- thing2(bar!), {:ok, bar!} <- thing3(bar!) do bar! end end Inspiration came from julia, where ! at the end of the function means "watch out, one of the parameters is gonna be mutated!"
- sodapopcan 6y ago