| > I'm not really sure what the appeal of Elixir as a language is actually supposed to be Easy: - rebinding
- higher-level OTP abstractions
- AST macros
- nicer, more readable syntax
- (optionally) cleaner stdlib
(Assuming you're not trolling: you chose to focus on features that can only be judged subjectively, and therefore can only be discussed as preferences. It's ok to have them, but actively displaying them is a bit pointless. Objectively measurable features of both languages put them very close together, with both having slight advantages over the other in different areas, on average making them almost equivalent. Especially compared to anything non-BEAM.) |
| |
| ▲ | asa400 a day ago | parent [-] | | Rebinding is not mutation. This seems pedantic but is an important distinction. None of the semantics of the runtime are changed. The data remains immutable. You probably know this. However, for the benefit of readers who may be less familiar: Erlang does not allow variables to be rebound, so it's somewhat typical for Erlang code like this: X1 = 8.
X2 = X1 + 1.
X3 = X2 * 302.
You cannot, say, do this: X1 = 8.
X1 = X1 + 1.
This is because in Erlang (and in Elixir) the `=` is not just assignment, it is also the operator for pattern matching. This has implications that are too broad for this post, but the key point here is that it's attempting to see if the the left side and the right side "can match".Whereas writing the same thing in Elixir would look like: x = 8
x = x + 1
x = x * 302
This is because Elixir allows `x` to be rebound, in effect changing what data `x` points to, but not mutating the underlying data itself. Under the hood Elixir rewrites each expression into something resembling the Erlang version.The practical effect of this is that if you for example insert a process spawn somewhere in between any of the lines that references `x`, that process gets its own totally immutable version of the data that `x` points to at that point in time. This applies in both Erlang and Elixir, as data in both is completely immutable. | | |
| ▲ | johnnyjeans a day ago | parent [-] | | It should also be noted that handling state like that is not really idiomatic Erlang. State is updated at a process level, thus traditionally you spawn another process which is trivial to do. On the BEAM that is fast enough for 95% of cases. If you really need mutation on local variables for performance reasons, you should already be writing NIFs anyways. State variables are what I think corpos call a "code smell". The BEAM/OTP isn't a number cruncher, there are better tools out there if you're doing a lot of that. Erlang is, at it's core, about constraint logic programming. It should be best thought as a tool for granular, scalable, distributable userspace scheduling. If you need something outside of that, NIFs or Ports. Both are quite nice. | | |
| ▲ | asa400 a day ago | parent [-] | | This has nothing to do with math or number crunching on the BEAM. This has nothing to do with mutation. This has nothing to do with performance. This kind of process and function-local static single-assignment code is all over the place in Erlang codebases. It's incredibly common. The other popular method is tail recursion. I searched for literally 30 seconds and found these: - https://github.com/ninenines/cowboy/blob/master/src/cowboy_router.erl#L139-L144
- https://github.com/ninenines/cowboy/blob/master/src/cowboy.erl#L201-L205
- https://github.com/ninenines/cowboy/blob/master/src/cowboy_http2.erl#L487-L506
|
|
|
|