bodhilogic
Elixir is touted as being a ‘Functional Language’ and the common characteristic of a functional language is that its ‘variables’ are immutable.
Other functional languages allow some tolerance for mutability, as long as some explicit ceremony is employed so that the developer knows he/she is ‘breaking the rules’.
it seems to me that the Pin operator should really be an ‘UnPin’ operator so that allowing a left side to be re-matched to a right side becomes an explicit operation i.e. the left side is immutable unless I use the ‘UnPin’ symbol - “I know that by writing ‘^a’ I am explicitly allowing a state change”.
Does this make sense or do I misunderstand something?
I’m not putting Elixir down - just trying to understand it.
Yes, I have read José’s github posting about why he allows re-matching. I am just thinking that allowing re-matching shouldn’t be the default behavior and that it doesn’t cost much time or effort to type one extra character to allow the re-match.
Trending in Discussions
Other Trending Topics
Chat & Discussions>Discussions
Latest on Elixir Forum
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
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










First 10 of 12 Posts
benwilson512
Rebinding a variable does not mutate data. If I have:
yis still%{foo: 1}. The data itself is completely unchanged. We have shadowedx, but that isn’t the same thing as mutability. Data and bindings to data aren’t the same thing. It can be a difficult thing to see at first for some, but the “tolerance for mutability” you speak of from other functional languages doesn’t even apply here, since mutable data is not a feature available in the VM.This is perhaps easier to see in a loop:
If
=were performing a mutation,xwould be10, but in fact it’s still just1. All that happens is shadowing / rebinding, and that naturally doesn’t work across lexical scopes.kokolegorille
In Erlang, this does not work…
But in Elixir it works
Because underneath, it’s doing
A0 = 10.
A1 = 11.
You might not like it, because it feels like mutation, but it’s not, it’s rebinding. Just consider this as a syntactic sugar. It’s useful when doing
conn = conn |> apply_some_change()
In the end, it does generate valid bytecode for the BEAM, and immutability is respected.
BTW You might prefer Erlang syntax, but You would lose |>
dimitarvp
You can use ETS for mutability if you really really need it (say, if you want a big data structure that must change often with minimal performance penalty; or caches).
The pin operator does not mutate. It allows you to match information stored in a variable instead of it being hardcoded. The official docs have pretty good examples, have you tried them in
iex?The
=does not assign per se; it matches a pattern and rebinds if the match is successful (namely the variable is internally now a different variable entirely; using the same name is a syntax sugar, and that variable simply points to a new immutable piece of data now; the old value is discarded). It never assigns, as @benwilson512 mentioned.cmkarlsson
While technically correct I think it leaves the impression that you are mutating, especially for newcomers to the language. If I’d guess this behaviour was put in because of two things:
and found it unpleasant.
Personally I to some degree see rebinding with the same variable name as an opportunity to rewrite that piece of code. In erlang the
A0..ANvariables stick out a bit encouraging you to rewrite. I think the risk of allowing re-binding is that it can potentially make it harder for someone whothinksit is mutability to learn how to think functionally.dimitarvp
I sympathize and I was quite shocked when I was learning Elixir, in several places. But the gulf between imperative and functional is big and there is not much we can do about it…
I agree, but IMO it all boils down to the discipline of the programmer in the end. I was using throwaway variables long before I ever heard of functional programming, for example. And then you have people writing an OOP library for Elixir. ¯_(ツ)_/¯
Some mind and brain bending is inevitable while one learns Elixir.
In the end it boils down to how adamant the programmer is about the way they want to do things.
bodhilogic
Fantastic responses!
Thank you all so much.
I suppose I just need to “retrain the brain” from a world of imperative programming to that of functional programming.
I had to go through a similar shift many, many years ago coming from iterative programming to the world of Prolog - you just have to learn to think differently ;).
I suppose a year from now, I’ll look back and laugh at myself for not appreciating the syntactic sugar that José took the time to build into Elixir.
Having said all that, I am really looking forward to exploring Elixir and becoming fluent in a ‘new’ way to program!
axelson
It would be nice if the pin operator was reversed but that would make the syntax quite cumbersome for some simple cases. Take:
^x = 10vsx = 10Also it would not be intuitive how to re-using a variable within a pattern match would work. Would you write
{^x, ^x} = {20, 20}?OvermindDL1
Honestly I’d probably have had elixir had two operators, one for assignment and matching with a pin, and another for matching and assigning only to new bindings else use a pin to override. The conflating of matching and the weird rebinding/assigning Elixir does right now is confusing to a lot of people.
So no, it’s not that the pin operator is backwards, it’s great for an ‘assign’ operator, the problem is that there isn’t a dedicated matching operator as well. Could use
:=for assigning and=for matching, or reverse it, or something else, or whatever. Someone could do it with a library.michalmuskala
How would that work in expressions where you bind some variables and match on others? Which operator would you use and why?
Also, what about pattern matching in case or function heads, where you don’t have the operator at all, yet still have the matching/binding behaviour.
sribe
It seems like you’re confusing mutation with re-binding. They’re not the same. Re-binding does not mutate any data; does not create any change that is visible outside the immediate scope.