In case people skim over this. One of the nice things about Erlang / Elixir is that the tcp/udp libraries are well integrated with the actor-model. Incoming data can just be another message.
You can flood your process this way and there's no feedback to the OS that you aren't actually handling the data, but there are flags / patterns to cleanly deal with that (e.g, using active: :once which is probably what most cases should be doing)
Further, for the tcp library, there are a handful of message boundary options that can really speed development. Set "active: :true, packet: 4" on the socket, and you're telling the library that each message has a 4-byte length prefix. It'll take care of the rest - on both the sending and receiving end. (pairing this with the built-in object serialization (term_to_binary and binary_to_term) makes it possible to achieve relatively complex logic across systems with minimal amount of code).
There's also a newish socket module that exposes an API which is more similar to what most programmers are probably used to.
I agree, if you are reading this please look more deeply at Elixir and Erlang. Unlike many languages that do things a different way Elixir/Erlang see real industry use at scale.
Erlang is a language I've recommended people read about for ages because it is different and useful.
Yes. I recently wrote an Elixir driver for MonetDB. I also wrote a CLI tool in Go for MonetDB and had to write a subset of the driver.
Pattern matching in general, and binary pattern matching specifically, made the experience (and the resulting code quality) night and day.
The big issue I have with pattern matching / binaries (aka, strings) in elixir / erlang is that doing it efficiently is, at best, a dark art and, at worst, impossible. This was drastically improved in OTP 22, but it's still opaque.
> The big issue I have with pattern matching / binaries (aka, strings) in elixir / erlang is that doing it efficiently is, at best, a dark art and, at worst, impossible.
Sorry, can you elaborate what you mean by impossible? Or maybe what you mean by efficient.
I just spent some time looking at some old code, and it does seem like OTP 22 solved any of the issues that I had run into at the time. My mistake, sorry about that.
Compiling with the bin_opt_info flag (erlc +bin_opt_info Mod.erl) will list the points in your code where binaries are created during pattern match, or any other points where binaries could be shared, but are not.
I really wish more languages had better handling for binary, such as in Erlang. I'm working on an implementation of a rather old networking protocol where frames are very bit oriented and writing code to to read and write individual bits feels so tedious.
Oh wow, I didn't expect to see this on here! I wrote this one night for fun, and then shoved it on a Raspberry Pi with Nerves, where it chugged away on my desk for a few months, listing all the devices connected to my network.
The code wasn't very complicated, and it definitely isn't perfect -- I'm not doing any load shedding or applying any backpressure -- but it was a ton of fun to write, and really demonstrated how great Elixir and Erlang are for these kinds of projects.
I didn't keep up blogging, but I did get more involved in open source after this post, and I've been actively coding for fun most nights again. Sitting down and building a small and easily scoped out project really went a long way toward bringing myself out of burnout.
I'm glad you enjoyed it! Some of these patterns are a little controversial, because they add extra layers of indirection + bloat the code, but I've personally always found that they make Erlang / Elixir much more readable.
One of my favourite talks is "Writing Beautiful Code" by Garrett Smith (of "MongoDB is Web Scale" fame), and he walks through refactoring a part of CouchDB (also in Erlang) by using some of these techniques.
Please add some kind of lighter background, the text today is pretty impossible to read. It looks interesting, but I just cannot stand the site. I get that it's a joke or whatever, but I bounced because of the background. I kinda want to read it, but couldn't.
You can flood your process this way and there's no feedback to the OS that you aren't actually handling the data, but there are flags / patterns to cleanly deal with that (e.g, using active: :once which is probably what most cases should be doing)
Further, for the tcp library, there are a handful of message boundary options that can really speed development. Set "active: :true, packet: 4" on the socket, and you're telling the library that each message has a 4-byte length prefix. It'll take care of the rest - on both the sending and receiving end. (pairing this with the built-in object serialization (term_to_binary and binary_to_term) makes it possible to achieve relatively complex logic across systems with minimal amount of code).
There's also a newish socket module that exposes an API which is more similar to what most programmers are probably used to.