Live data from Hacker News

Unpacking Elixir: Concurrency

underjord.io

41–50 of 138 posts

Re: Unpacking Elixir: Concurrency

#41
post #12

The deal-breaker for me with Elixir has always been the lack of real Elixir vectors rather than the crappy Erlang array library. Yes, I know you can use a Map with numeric keys but that's not the same.

One of the many reasons I left Erlang is the lack of user types. I understand how the BeamVM got there. You build into the system the idea that there may be multiple nodes that communicate over the network. Those nodes will routinely pass through states where they are on different versions of code. Those types may have to be upgraded at upgrade time. Having no user types in your type system, just a fixed set of dynamic types that are relatively simple, mean that when it comes time to upgrade, you don't have to figure out how to load two method sets for the same module at the same time (and the corresponding multiplicity of states that can emerge beyond that); the new code can get the old value safely and easily since it has no methods on it, examine it, and upgrade it in a principled manner.

Nifty, powerful, and simple, like so much of Erlang.

But also like so much of Erlang, I think the modern approaches (several of them) that languages take to serialization is better. It's a good first pass cut at the problem, but I prefer all of the GRPC approach to the problem, the JSON approach to the problem, and honestly just letting the chips fall where they may with most modern serialization libraries. Treat the remote system as not entirely trusted and handle the messages with a bit of skepticism generally works out for quite a bit of scaling. And you get user types back, which means you are no longer stuck on the BeamVM's quite anemic data types.

If you look at the underlying implementations of an Erlang map, you'll see why you're not getting vectors anytime soon.

    1> dict:append(a, b, dict:new()).
    {dict,1,16,16,8,80,48,
          {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
          {{[],[[a,b]],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}}}
It's a big pile of linked lists storing assoc lists held together by tuples, with all the component value being dynamically typed. It's nice they didn't cheat on that, but it is... not the most efficient approach to dictionaries, just the one enabled by their type system, such as it is.

Re: Unpacking Elixir: Concurrency

#42

Earlier quoted context omitted.

Maps are hashtables, Vectors are a contiguous area of memory where each element can be access by index referring to a specific address in that memory. Vectors are usually also homogeneous about the data they hold, because each element should occupy the same fixed amount of memory, such as i*item_size gievs you back the offset of the element i in memory. Anyway, in Elixir you can use the Erlang's :array module

I'm pretty sure erlangs :array is just a skin over tuple, so it's ~O(1) but not contiguous. might be O(log n) for dynamic arrays. The only truly array datatype in Erlang is :atomics

Erlang tuples are contiguous in memory for primitive values https://blog.edfine.io/blog/2016/06/28/erlang-data-represent...

Re: Unpacking Elixir: Concurrency

#43

Earlier quoted context omitted.

This. I don't want to be in an event loop by default.

Hate to break it to you but in the BEAM you're always in an event loop.

No really. The scheduler isn’t really like an event loop. The scheduler will only allow a task so many units of execution before pulling it off the processing queue and scheduling other work. You can block an event loop, but not the scheduler.

Re: Unpacking Elixir: Concurrency

#44
post #12

The deal-breaker for me with Elixir has always been the lack of real Elixir vectors rather than the crappy Erlang array library. Yes, I know you can use a Map with numeric keys but that's not the same.

There is an array library which creates a MapArray type but with list semantics and conforms to Enum and Collectable protocols -https://hexdocs.pm/arrays/Arrays.html. I've found it useful for when I need an array. Then there's NX for vectors - needing extra deps, granted.

Re: Unpacking Elixir: Concurrency

#45
post #41
post #12

The deal-breaker for me with Elixir has always been the lack of real Elixir vectors rather than the crappy Erlang array library. Yes, I know you can use a Map with numeric keys but that's not the same.

One of the many reasons I left Erlang is the lack of user types. I understand how the BeamVM got there. You build into the system the idea that there may be multiple nodes that communicate over the network. Those nodes will routinely pass through states where they are on different versions of code. Those types may have to be upgraded at upgrade time. Having no user types in your type system, just a fixed set of dynam…

Note that Erlang has maps since OTP 17, which I believe are implemented more efficiently than dicts.

Re: Unpacking Elixir: Concurrency

#46
post #39

Disckaimer: I have never used Elixir in any serious capacity, but I have done a good chunk of Erlang. Concurrency in Erlang sort of frustrates me...not because it's bad, but because when I use it I start getting pissed at how annoying concurrency is in nearly every other language. So much of distributed systems tooling in 2023 is basically just there to port over Erlang constructs to more mainstream languages. Obviou…

Can you give some examples?

Re: Unpacking Elixir: Concurrency

#47
post #12

The deal-breaker for me with Elixir has always been the lack of real Elixir vectors rather than the crappy Erlang array library. Yes, I know you can use a Map with numeric keys but that's not the same.

So what do you use real arrays for? For 80% of programming lists are just fine. Are you doing cpu-bound numerical calculations?

Interviewing for when the interviewing is expecting an array (sarcasm intended).

All kidding aside, unless I'm interviewing at an Elixir shop, I've learned that Elixir is a little too weird for interviewers who don't know Elixir very well.

Re: Unpacking Elixir: Concurrency

#49

Earlier quoted context omitted.

There’s definitely a bit of a learning curve if you’ve never written in a language where everything is immutable. Certain problems have to be approached in a fundamentally different way if you can’t mutate state. Fortunately there’s Agent/OTP, but again, pretty different than other (or popular with beginners - js/python/java) languages.

You really shouldn't be using agent for mutable state. Kind of annoying that the docs push you to that. Agent is most useful when you need to tie the transient lifetime of some state with something else (think: compilers). Otherwise, it's generally better to use a database, (or ets, if you need performance), GenServer/gen_statem if you need reactive events attached to the state. Agent is just a wrapper over GenServer…

I love elixir and am very comfortable with functional programming and generally prefer it. But being told you have to write a state machine instead of just += a var is an excellent experience in believing elixir is harder than python.

Re: Unpacking Elixir: Concurrency

#50
post #39

Disckaimer: I have never used Elixir in any serious capacity, but I have done a good chunk of Erlang. Concurrency in Erlang sort of frustrates me...not because it's bad, but because when I use it I start getting pissed at how annoying concurrency is in nearly every other language. So much of distributed systems tooling in 2023 is basically just there to port over Erlang constructs to more mainstream languages. Obviou…

I fell in love with Erlang pretty quickly, and it’s hard for me to enjoy writing other languages. Simple concise syntax, pattern matching, immutability, error handling without branches all over the place, concurrency… it’s hard to walk away from that.
Post reply on HN