a) Ubiquity — everything understands HTTP. Erlang nodes only talk to Erlang (or a compatible runtime)
b) Because there are no middleware standards (REST, GraphQL, OAuth, etc.), you must build or integrate your own abstractions
c) Giving up infrastructure (reverse proxies, load balancers, CDNs), You handle distribution yourself or through OTP design
d) Interoperability with browsers and APIs, requiring bridging via something like Cowboy or gRPC gateway
setcookie secret in Erlang does not create or use an HTTP cookie, SSL certificate, or HTTPS connection. It sets the Erlang distribution cookie, a shared secret string used for node authentication within the Erlang runtime system (the BEAM VM).
Erlang’s built-in distributed networking subsystem allows them to connect to each other if:
1) They can reach each other over TCP (default port 4369 for the EPMD — Erlang Port Mapper Daemon — plus a dynamically assigned port for the node-to-node connection).
2) They share the same cookie value (here "secret").
The author's insight "No HTTP. No REST API", reframes the reality that Erlang moves things down the ISO OSI model - HTTP being on layer 7 and TCP being on layer 4. Erlang therefore misses the "benefits" of operating on a higher ISO layer, but gains powerful advantages of operating on layer 4:
i) True concurrency
ii) Transparent message passing
iii) Fault tolerance
iv) Soft real-time guarantees
v) Persistent cluster connections
Erlang’s design assumes a trusted, closed system of cooperating nodes, not a public Internet of clients. In other words, Erlang doesn’t live below Layer 7 — it IS its own Layer 7.
OTP includes an http client and server. And ERTS includes an http mode for sockets. You may prefer 3rd party http servers (yaws and Cowboy are popular) or clients, but you have options that come with Erlang.
[No comment on b; I'm not sure I aprechiate the concept of standardized middleware]
> c) Giving up infrastructure (reverse proxies, load balancers, CDNs), You handle distribution yourself or through OTP design
You can put all this stuff between the users and you Erlang cluster. Within your Erlang cluster, I don't think it makes sense to leave the cluster and go back in... If you had a large server process in [language of choice], you probably wouldn't send request out to a load balancer to come back into the same process. If you have an n-tier system you may use a load balancer for requests to the other tier... In Erlang, the simplest analog is processes that serve the same request queue would join a pg group, and processes that want to send a request send to one of the members of the group.
> d) Interoperability with browsers and APIs, requiring bridging via something like Cowboy or gRPC gateway
If you want to talk http, you need something that talks http; there's at least 3 reasonable options, plus an http parser for sockets so you can do it yourself without as much fiddly bits. I guess I don't understand what you're looking for here.
- REST (mentioned, but what kind of REST? Rails style REST? Just plain http resource endpoints? - GraphQL (mentioned) - gRPC - SOAP - JSON-RPC - Thrift - CGI (ok not really in the same category as the above) - Some weird adhoc thing someone created at 3am for "efficiency"
I'm actually fine with most languages deferring to their respective communities, maybe building on core libs like https://www.erlang.org/docs/17/apps/inets/http_client to handle the transport layer.
As an aside, funnily enough you can get JVM <-> BEAM interop via https://www.erlang.org/doc/apps/jinterface/jinterface_users_... I don't necessarily recommend it but it's possible
The simplest RPC protocol is where you connect to a TCP socket, send a newline-terminated string per request, and get a similar response back. You don't need HTTP for that - you might still want to use JSON. What does HTTP give you in addition?
It's presumably still not something Erlang directly supports.
HTTP2 offers lots of nice features like stream multiplexing and socket re-use. I guess also encoding standards? Less of an issue in this day and age where everything can work with utf-8.
Presumably the fact that you can interoperate with other systems not part of BEAM is desirable too.
You're sort of confusing the purpose of Erlang distribution, so I would turn this on its head with the following questions:
Do the Python, Ruby, FORTRAN, Lua, etc, etc, runtimes provide built-in, standardized, network-transparent RPC, [0] or do you have to roll your own using some serialization library and network transport library that might not be The Thing that everyone else who decided to solve the problem uses? Do note that rolling your own thing that is the "obvious" thing to do is still rolling your own thing! Someone else might make a totally reasonable choice that makes their hand-rolled thing incompatible with yours!
I think this confusion influences the rest of your list. Erlang has several HTTP servers written for it [1], but it is not -itself- an HTTP server, nor does it use HTTP for its network-transparent RPC, service discovery, and monitoring protocol.
> The author's insight "No HTTP. No REST API", reframes the reality...
With respect, you're confused. The authors insight can be reworded as
> I can do RPC with no hassle. With just three symbols, I say 'Send this data over there.' and the runtime handles it entirely automatically, regardless of whether 'over there' is running in the same Erlang VM as the calling code or on a computer on the other side of the globe. With equivalent ease, I can say 'When someone sends me data, call this function with the transmitted data.' and -again- the runtime handles the messy details.
When I was first introduced to Erlang's distribution system, it also took me quite a while to detangle it from what I knew about the Web World. Reading through the 'Distribunomicon' chapter of Learn You Some Erlang [2] helped to knock those erroneous associations out of my head.
[0] ...let's not even talk about the service discovery and process/node monitoring features...
[1] Some of which totally do support middleware gunk.
[2] If you've not read LYSE, do note that it was first published in 2010 (and got an update in 2014 to cover the then-very-new Map datatype). Because the folks who work on Erlang tend to think that keeping old code working is a very virtuous thing, the information in it is still very useful and relevant. However, it's possible that improvements to Erlang have made some of the warnings contained within irrelevant in the intervening years.
Concurrency is important, but if you are not familiar with concurrency primitives like mutexes, condition variables, barriers, semaphores, etc. and skipped directly to the actor model, that's a bit like you care a lot about concurrency while not caring at the same time.
Functional programming is great, but your CPU has registers and the way it works is closer to the imperative paradigm.
His PhD thesis explains the thinking behind Erlang, especially how it handles failures, message passing, and concurrency. It was last updated in 2003, 22 years ago, time really flies!
This really helps systems from muddling along into bizarre states, where things are going awry and nobody knows why.
I'm still more of a infrastructure guy than a software developer, but working with such incredibly smart people was a delight. Basho was good at hiring people who could learn Erlang (and, perhaps unsurprisingly, was almost entirely remote).
[0]: https://pragprog.com/titles/btlang/seven-languages-in-seven-...
I'm saying this with complete sincerity: WHAT IS IT THAT YOU PEOPLE SEE!? What is the fun? What are you addicted to? Typing and seeing the output? Solving a problem?
I feel like I am missing out on some amazing life altering experience when I see people state that. The same thing I have with the article - what does it mean to love a programming language?
Expressiveness: I could express a solution to a problem with very few lines of code and without the clutter of housekeeping operations like memory management.
Recursion: Erlang properly introduced me to recursion whereas I hadn't encountered it before. This is again related to expressiveness. There is something strangely beautiful about seeing a problem solved using recursion elegantly.
Message passing: when I was trying to figure out how Microsoft's C++ socket classes were implemented and I dug into the code, it turned out there was a hidden window for every socket created and messages were being passed to/from it, but message passing wasn't available anywhere in Visual C++ as a first class construct (at least as far as I remember it). I was overjoyed when I discovered that message passing was a first class citizen in Erlang and how much easier it was to implement concurrent programs than using native threads in C++.
Compared to OO programming in C++ where I was never sure whether I was using inheritance correctly, whether I needed inheritance at all, memory management, difficulty with threads, writing code in Erlang was a breeze.
And the whole support for distributed programming, hot code loading, list comprehensions! I fell in love again with Erlang when I discovered list comprehensions. Man, I could go on.
Also, some languages just really stink— slow compilation times, obscure errors, loads of footguns and require much more care and focus on things which are orthogonal to the problem you’re trying to solve.
And then, one day you discover the chainsaw, and the fact that you should cross cut.
Suddenly cutting wood no longer feels terrible, it's smooth, stuff works the way you expect. Your chainsaw turns out to have features for all kinds of wood and for many different kinds of joinery that you were hand carving before. It turns out that your chainsaw can be used to control an army of chainsaws without having to do anything at all. You just declare it to be so and it works.
Instead of focusing on your tools all day long you find yourself focusing on the thing that you are actually trying to solve. Where you needed 50 people before, now you need 5.
Programming languages stress reusable code, where you get reusable processes (eg interface to the SMSC)in Erlang, which you would need messaging servers in other languages.
As for it being fun and addictive, I'm retired. I can write code in any language I want, or don't write at all, and I choose to write in Elixir.
In that sense, Erlang isn’t really different from any other functional programming except that it also ships with a lot of actor / message passing concurrency dogma which solves a different and equally delightful set of problems (low-bug concurrency) at the same time.
So it’s a double hit of two great ideas in one paradigm.
*Oops, no pun intended.
A good example is mutable state: for a bunch of people, functional languages that enforce immutability has this calming effect, since you know your data isn't mutating where you can't see it. You've been burned by C++ code that's passing references as arguments, and you don't know if the list you received as an argument will be the same list after you've passed it as an argument to a different function. You don't know if you can futz with that list and not make a problem for someone somewhere else.
But for most people, they much prefer how "intuitive" it is to have mutable state, where they just change the thing in front of them to be what they need. This is especially true in the context of for loops vs. recursion: "why can't I just use a for loop and increment a counter!" A lot of Golang folks love that it explicitly rejects functional mapping primitives and "all you need is a for loop."
It's a very personal decision, and while IMO it doesn't really matter for the ultimate business success (usually companies fail because of something that's not tech-related in the least), it does shape _how_ it feels to work on a tech stack, and I'd argue, what kinds of technical problems you run into.
I've fought null pointer exceptions longer than I want to in C# servers and Python code. Usually because we're introspecting into a message that a system sent us, we expect it to have a field on the message, we failed to check for the existance of that field / the field to not be null, and bam null-pointer exception.
Sure, add another guard clause... Every time you run into it. Every time the server crashes and it's a serious problem and someone forgot to set a restart policy on the container... Sometimes you don't know exactly what cascade of messages caused the whole thing to unwind. So tedious. So repetitive.
With GenServers, you've carefully defined that those parts of your system have active, in-memory state, and everything else must be a pure function. Messages come in a FIFO queue to your GenServer.
With pattern-matching, you define exactly what shape of message / fields on the message, and if it doesn't match that, you can either log it, or crash that GenServer.
Which normally would be catastrophic, but since you tied your GenServer to a SupervisionTree with a restart policy (which is trivial to write), if anything happens that you didn't expect, you can Let It Fail. The GenServer crashes and is immediately restarted, with a clean slate, with the correct peer-services in the correct state. Sure, the message that crashed your server was "lost" (there are options to push it to a dead-letter-queue on exit) and you have a bad-state and bad-message to debug in the crash-dump, but your server is still going. It hasn't stopped, it just dropped unexpected messages and has a deterministic recovery pattern to clear all bad-state and start again.
So instead of your message handling code starting with a bunch of defensive sanity checks, with the real meat of the function in the last 5 lines.... you just say "My GenServer is here in this SupervisorTree, I expect an inbound message to look roughly like this, and I will do this with it, done". Suddenly the server will handle the messages it knows how to handle, and everything it cannot handle it will drop on the floor.
Think of this! The server just stays up and keeps going! Anything it cannot handle is not a fatal exception, but a log message. And you didn't have to bend the code into an unnatural shape where you trapped and logged all exceptions and bubbled them up in specific error checks... it's just designed to do it that way out of the box.
And for me, what it comes down to, is, doing powerful things in Erlang/Elixir is trivial where it would be really convoluted in other languages. When applied to the right problem, it genuinely makes a whole class of problems evaporate, and that's addicting.
These are just bombastic claims and empty verbiage which has become "language du jour" in the Interwebs. This came into vogue during the software boom of the 90s when companies started asking for "rah-rah passion" and everybody started making such inane statements to get through interviews.
As for the submitted article, it is just pedestrian (there is nothing in it really) with some pretty posturing/language to sell it.
But some of comments in this thread are informative.
Also this:
https://www.infoq.com/presentations/Simple-Made-Easy/
For me, there's a dopamine hit in taking a complex problem, and breaking it into simple interacting parts that solve the problem in an elegant way. Overly complex programming languages add lots of incidental complexity that slow down this process. A clear, simple, consistent semantics accelerate this process.
If that doesn't inherently excite you, the life altering experience probably isn't going to happen for you.
I'm a hobbyist high-availability dork, so the idea that I could update my program without interrupting any user of the program was very, very attractive to me. I'm also quite sick in the head and have a life-long torrid love affair with Bash's switch statements, so Erlang's "pattern match to make most decisions" syntax was a huge attracter.
Having said that, I didn't really get Erlang until I had a project for which it and the OTP were a good fit. I needed to build a server for an unfamiliar-to-me protocol, so I expected to regularly have protocol handlers fail due to incorrect implementation. This server would be long-running, so VM startup time was not a problem. This server would perform next-to-no number crunching. This server could be very effectively modeled as a swarm of message-passing processes. The core functionality of the server was best modeled as an FSM.
Erlang's "share nothing, use message passing" design, along with OTP's supervisor and friends kept my server up and running while my protocol handlers exploded because of incorrect or absent handler code, or too-pessimistic assertions about the valid bounds of input data. Hot code reloading let me fix broken code paths (or experiment with non-broken ones) without affecting users of other code paths in the server. [0] The built-in FSM library made it trivial to express the parts of my program that were an FSM as an FSM. Not only did Erlang's syntax satisfy my sick fascination with Bash's switch statements, it permitted me to write nearly all of my server as simple, sequential code and let Erlang/OTP handle the nasty problems of concurrency for me.
Oh yeah, and the extremely high quality of Erlang's documentation was really helpful. In the reference manual for the standard library, the documentation for every single function provided in Erlang/OTP told you the valid types and acceptable ranges/values for both function arguments and return values. They told you which functions would throw, what would be thrown, and under what conditions. They also described what the function did, and -when needed- why it did it. I could be confident that if I programmed according to the docs, then my program would behave as the docs said it would... unlike where documentation for most Web Development stuff leaves you. [1] There's also official documentation about the design of Erlang/OTP and the reasons behind that design. Those docs (along with Learn You Some Erlang) definitely helped me understand Erlang and OTP.
Like I said... if your project isn't a good fit for what Erlang provides, I think you're not going to get what makes Erlang/OTP special. But if it is, there's a very good chance that you will.
[0] Supervisors + hot code reloading made it emotionally really easy to build my server incrementally. Knowing that I didn't have to get the entire protocol right to have a server that would never die was calming. As was knowing that implementation failures (or deliberately unhandled parts of the protocol) would provide me with usually-good diagnostic information, rather than a core dump (or nothing at all(!)).
[1] This was prior to the big redesign of Erlang's docs to ape the style used by HexDocs. Whoever did that redesign very, very clearly did not understand what made Erlang's documentation so good. Switching from EBNF-ish to raw Erlang spec format not only takes up far more vertical space, but adds yet another new thing someone new to Erlang needs to learn. But far, far, far worse is that some of the documentation about the valid ranges of input to functions has been lost.
Some of the comments here are far more informative.
Erlang gets a lot of stuff right for scalable web based stuff, and even though there are many of its influences that have by now made it into other languages and eco systems it is still amazing to me that such a well thought out system is run with such incredible modesty. You'll never see the people behind Erlang be confrontational or evangelists, they just do what they're good at and it is up to you whether you adopt it or not. And that is an interesting thing: the people that are good at this are writing code, not evangelizing. If I had to reboot my career I'd pick this eco system over anything else, it has incredible staying power, handles backwards compatibility issues with grace and has a community that you can be proud of joining. Modest, competent, and with a complete lack of drama.
The big open source projects where pretty much all like that in the past, in the 80's/90's/early 2000's - in that respect they feel like a pleasant anachronism before everything needed to be promoted/self-promotional influencer like, the users did the evangelism but the creators where usually much more chill.
Obviously the vast majority of open source projects are still like that but there is definitely a lot more in your face promotion of things that feels different somehow almost aggressive/corporate style even when there is no paid product.
Not knocking the ones who do it, if it's open source they can sing it from a mountain top for all I care, the license it's under matters more.
Take Swift for example. A giant gatekeeper of a corp decided to make it the only (reasonable) way to build apps and so it exists, powered by countless indie developers constantly creating content around it. Would Swift be a thing without everyone being forced to use it? I don’t know, but I don’t think so.
So in some ways we’ve traded unique and effective solutions to “popular and mainstream” things that scream the loudest. You wouldn’t get fired for choosing Swift. Or Azure.
I must have been living in a different world then. I mean maybe in the 80's and 90's but I feel like people acting weirdly obsessive about a piece of tech and going about evangelizing it every where, usually in a detached from reality kind of way, goes back to at least newsgroup, when suddenly you could have an audience outside of physical event (with their limitation and all). I mean there was the text editor flame wars, and I am sure you can find post like "why are you not using language/database/tool X instead of Y???!!" in the most ancient of mailing list and forums.
For those who collaborate with open source for political/ideological reasons (which does not need be the case), it makes sense to join the battle for attention.
As long as the product isn’t compromised in the way, I think it’s very good to see open source influencers.
I've learned Elixir in 2016 after a lull in my interest in programming languages, and 9 years later it's still my favourite environment by a country mile. It's not the language per se, but the BEAM, the actor model, the immutability — just makes sense, and doing things the C/Rust/Javascript/Python way is like building bridges out of cardboard.
For example, I've stepped into the world of game dev and Godot, which is fantastic and uses a regular object-oriented model. After trying to build a non-trivial desktop app with it, my thoughts are consumed by the fact that mutable state and object orientation is the silliest idea, and I'm speaking as someone that really got into Smalltalk and message-passing objects.
I don't even need actors and OTP, I just want some immutable data structures and functions operating on them. Erlang/Elixir are fantastic to build servers, but there is a sore lack of something closer to the metal within 80% the speed of a native language. I would build an entire operating system out of it. Why has no one put microkernels and Erlang into a blender? I know there's QNX, but it's still UNIX, not Erlang.
I have nothing but admiration for Erlang, and it is, without a doubt, one of the most inspired languages I've encountered in my career. But when I was at university in the late-ish nineties, they taught us Haskell as "the language of the future." So I guess some languages are forever languages of the future, but they still inspire ideas that shape the actual future. For example, Erlang monitors were one inspiration for our design of Java's structured concurrency construct [1].
If you're interested in another "language of the future" that bears some superficial resemblance to Erlang, I'd invite you to take a look at Esterel (https://en.wikipedia.org/wiki/Esterel), another language we were taught at university.
[1]: https://docs.oracle.com/en/java/javase/25/docs/api/java.base...
That's a very good question. There are some even lesser known dialects out there that do this but you are going to find it hard to get to the same level of feature completeness that Erlang offers out of the box.
QNX and Erlang embody quite a few of the same principles, but QNX really tried hard to do this at the OS process level in a way that destroyed a lot of the advantages that doing the same under Erlang would have. I think the main obstacle is the fact that the CPU does not support reductions natively. Maybe you could take it a step further and design an FPGA CPU that implements the core features of Erlang at the hardware level?
That would be an absolutely awesome project. Usually when you can think of it someone has already done it so a bit of googling would be a good way to start with that.
As someone who built an entire startup in elixir, its a good time to bring up that elixir has an excellent interop with rust via rustlr.
Peer Stritzinger (https://stritzinger.com/) the guy behind the GRiSP project (https://www.grisp.org/) has integrated Erlang + RTEMS (https://www.rtems.org/) for the embedded GRiSP Nano HW (https://www.grisp.org/hardware#grisp-nano-details-section and https://www.grisp.org/blog/posts/2025-06-11-grisp-nano-codeb...)
His HN account with some technical comments - https://news.ycombinator.com/threads?id=peerst
https://github.com/cloudozer/ling
Erlang on Xen.
But also one of today's unlucky 10K as it hasn't been updated for 10 years.
Clojure has that for you. plus its jvm which means for your desktop use cases it works. hell with graalvm can be ported to native.
I can't find any.
There's been little drama, the language is relatively stable, the community has always been there when you need them but aren't too pushy and flashy. It all feels mature and – in the best possible way – boring, and that is awesome.
It's all so boring it's wonderful.
So there are definitely unpleasant people around, just like in many ecosystems. Maybe less so, but I don't know about that. The question is only whether one lets that keep one from doing whatever one came to do.
Every group of > 10 people will have at least one jerk in it.
Can I interest you in my Rust project hosted in Jujutsu VCS?
That said, the metaphors are so elegant, the key concepts so well chosen -- yes, the initial onramp may be a cognitive slog, but it's well worth it. It makes everything downstream so much easier.
That's really interesting... My wife, who has no real mathematical background had the EXACT same reaction when I was trying to teach her some simple programming. I tried to explain that equals in that context was more of a storage operator than a statement that said line is true. She found it very frustrating and we gave up on the endeavor shortly thereafter.
I've personally always had a soft spot for languages like TI-BASIC that use a storage operator rather than overloading = so for example:
X + 1 -> X
I wonder if I should try a functional language with her.
Also, various ways of assignment:
Pascal style:
x := x + 1
Scheme: (set! x (+ x 1))
Forth: x 1 + x !I guess I got through that when I was 7 on a pass-me-down ZX81 from a relative who just had upgraded to a Spectrum (I assume).
I mentally called bull when reading boragonul's story because:
a) BASIC has a REPL
b) Kids back then had near infinite patience/time.
c) These computers came with pretty good manuals explaining BASIC
There was very little external stimuli. As an example: TV broadcasters in Europe were literally mostly shut off during the day to save power. Radio was on all day, but it was 99% boring adult stuff.
Or, perhaps, preprocess left-arrow to equal?
Customizing a language to taste. Especially for shallow syntactic issues. Like "no multi-line string literals allowed ... I'm sorry, that's just not ok". Or "ok kid, what nicknames would you like to give the keywords today"?
When programming for just fun, I'll sometimes go "this aspect of the language bugs me - I could of course just live with it... but here, I think it will be more fun not to". So for recent example, a few lines of recast.js ast tweaking, and I could use infix unicode mathematical symbols as javascript functions.
I wonder if one could teach programming by build-your-own language. Perhaps even of the video-scanned desktop variety. "Draw a circle around your toys to create a collection. Label it with a letter. Now you can sort/filter it by..."
X := X + 1 is perhaps less confusing, even if meaning the same thing.
Eshell V15.2.6 (press Ctrl+G to abort, type help(). for help)
1> X = 1.
1
2> X = X.
1
3> 1 = X.
1
4> X = 2.
** exception error: no match of right hand side value 2
5>I think an easy way to look at it, for someone coming from a math background, is to think of programming lines as instructions, instead of statements. x=x+1 can be then read as "let x be x+1", and that's it.
X’ = X + 1
DELETE X
X = X’
Even if you treat it as “storing a value in a slot”, a comprehensive model of the operation needs to model the fact that the value of the slot changes over time. So another way to look at it would be: X_t1 = X_t0 + 1
…except that “X” is shorthand for “the latest binding that uses this name.”For example
X = X + X
is really Xv2 = Xv1 + Xv1x(0) = 1
x(1) = x(0) + 1
There's no way to reference the subscripts. They're implicit and the language manages it for you. Ask her to think of the Kronecker delta function and it's definition.
x ← x + 1
Although you'd need to type x _ x + 1
and it might copy/paste as x := x + 1It's ridiculous, usually fake and hide the biases of those who nurtured them to believe whatever they believe, even if it's by pure imitation.
So you're absolutely right to call BS.
X = X + 1
and equality as in
IF X = 3 THEN 'Do something
and it's as natural as 'to dust' meaning both removing the dust and adding dust, depending on context, and 'to sanction' meaning both to approve and to punish. And the Prolog way seems all good too. There are more than one way to think about things.
I gave a talk at Midwest.io (sigh, such a great conference, shame it faltered) building Erlang from the ground up, starting with the = sign and the implications (side effects?) of it being a runtime assertion of truth in addition to a binding.
I don't think this is something that keeps someone from programming. If it does, then the other 100000 hoops won't be better, every trade has its "why the fuck is this the way it is" moments.
If you'd still try programming with her, I think you could start with a visual programming thing. Maze from Blockly Games is a simple online logic game that can be overcome with visual programming. No need to register or anything. The levels get progressively harder, as it teaches to apply programming concepts, and makes the player combine them. As a programmer, I found the game really fun, and I think it's suitable for beginners as well, seeing how for example LEGO used a very similar system for its programmable sets.
Not everybody is wired the same way. That exact thing happened to me, it was some kind of mental block. And when that fell away I found the rest of programming to be fairly easy.
Sum = n(n+1)/2
It's colourful language, but it's just a stand-in for other properties you might care about. For instance, in head(sort(list)), will the whole list be sorted, or will the smallest element be returned? In atomically(doThis(); doThat()), will doThis be 100% reverted if doThat fails? If you stick to pure functions (and in the second example, STM) then you can unfire the missile!
AFAIK, Erlang just fires the missile "over there", not "over here". The author jumped from:
(X = X + 1) is bad
to (mailbox = mailbox + message) is so simple!
I'm not bashing the BEAM, or the ease with which one can send messages (as an Actor language), but I am complaining about the lack of tooling to write non-missile-firing functions on a single node (as a Functional language).The author did not say this at all, they barely even touched on capabilities of erlang/OTP. Their focus was on the functional syntax of Erlang.
> For instance, in head(sort(list)), will the whole list be sorted, or will the smallest element be returned?
Your point isn’t clear. The functions have a clear nested call sequence, take a list, sort it, get the head.
Also how is it any different than Haskells `head (sort list)`?
Two separate Erlang nodes. On different machines, different networks, different continents if I wanted. And they could just… talk. No HTTP. No REST API. No serialization headaches. Just message passing. Just actors doing their thing.
> Their focus was on the functional syntax of Erlang.They didn't write any Erlang until the ping/pong example, which doesn't have any functions. What does pong() equal? Is it equal to itself even? What's its domain and range? If I wrote a unit test for it, what test inputs would I give it and what outputs would I assert?
My current stack is Elixir + Rustler on server and Rust + Wasm at frontend. Thanks for reading :)
I ran into this issue and I'm not sure if it's just a me thing.
When sending the message from the Pong REPL, the following didn't work for me:
```erl {ping, 'ping@localhost'} ! {pong, self()}. ```
When I checked, the PID of `self()` is different to the PID of the registered `pong` process. I needed to change it to the following:
```erl {ping, 'ping@localhost'} ! {pong, whereis(pong)}. ```
This sends the correct PID to the Ping process and we have an infinite loop counting up.
The multiprocess stuff is cool too, but a premature optimization for what I was doing. If I needed to scale, I don't know if that'd be the chosen approach.
Also, I'm sure my personal experience isn't necessarily true for everyone... so weight this anecdote accordingly.
Would you mind telling me your elxir program about? Is it a webapps or something similar?
Wait, is there something I don’t actually understand about recursion? When a recursive function calls itself, is that not a loop?
defmodule Server do
def start_link do
spawn_link(&loop/0)
end
defp loop do
receive do
msg ->
IO.puts(msg)
loop()
end
end
endOnce you get it, it's obvious, but if you're not already familiar with the notion, the understanding can be pretty amazing.
It is declaring a relationship, between the previous value and the current. One way or another, youre defining transformations.
I mean even in the sum example, you see the statement "N is n-1" which is the exact same thing as x = x+1 with = swapped for "is"
x := x + 1
syntax better, or the let x = 2;
syntaxThat wasn't actually what the example said. It said N1 = N - 1, and continued using the N1 value somewhere else. In that example, no actual mutation occured.
Then I have found the code that is a heavy user of closures is harder to understand even if it is single-threaded and closures can pass arbitrary state even if the state is immutable.
What I have found useful is persistent data structures. Those really simplify modelling. But then those can be used in imperative languages as well.
-module(ping).
-export([start/0, ping/1]).
start() ->
register(ping, spawn(fun() -> ping(0) end)).
ping(Count) ->
receive
{pong, Pong_PID} ->
io:format("Ping received pong (~p)~n", [Count]),
Pong_PID ! {ping, self()},
ping(Count + 1)
end.
I am not against functional programming, or using the tools you love, but at least make a valid argument about it ;)Like other folks have said, show the equivalent C program and then we can have a discussion about implementation complexity and comprehensibility.
Do note that the equivalent C program permits IPC between two instances of the program that could be either running on the same machine or could be running on different machines connected by an IP network.
Edit: For general information, here's an Erlang implementation of increment and swap. Swap is made a bit complicated because Erlang doesn't support multiple returns... returning a tuple or list is the way that's handled, so I had it accept a two-element tuple for consistency with what it returns:
increment(A) -> A + 1.
swap({A, B}) -> {B, A}.I am just disagreeing with the fact that C is hard to parse.
I have a toy replacement for syslog.
i supervised an LLM writing a discord-esq chat program that implemented a imaginary JMAP extension called 'JCHAT'.
i had the LLM write a Erlang based dimensional accounting system
So far in real life i don't have any uses, which is a shame because it's a great language and OTP comes so batteries included I can think of many use cases.
Not sure if you want to call it a screwup or bad grammar or whatnot, but it is perhaps the huge mistake that the "equals" sign was used for something that feels like, but emphatically DOES NOT mean, "is equal to."
It's "put this into that". It's an action verb. Should have perhaps insisted on x <- x + 1 or maybe better x + 1 -> x
The difference is that it is an instruction. Conventional mathematical notation, while declarative by default, switches into instruction mode just the same with the "let" keyword. The usage of the "=" operator then becomes equivalent: e.g. let x = 1.
But as the aforementioned x = x + 1 comes from notations that are never declarative, where every statement is an instruction, the "let" keyword is unnecessary and redundant. You already know you are looking at an instruction.
> Should have perhaps insisted on x <- x + 1 or maybe better x + 1 -> x
While that would obviously work, it strays further from the conventional notation. Which doesn't matter to the universe in any way, but the topic of discussion here is about trying to stay true to conventional notation, so...
> Other fiddles in the transition from BCPL to B were introduced as a matter of taste, and some remain controversial, for example the decision to use the single character = for assignment instead of :=.
I think Ken did most of the early design of B and DMR came along later to help with C. Ken has a famously terse style, so I can definitely see it being on brand to shave of a character from `:=`, which is what BCPL uses.
It's sort of a tricky little syntax problem. It makes perfect sense to use `=` for declarations:
int x = 1;
At that point, you really are defining a thing, and `=` is the natural syntax for a definition. (It's what BCPL uses for defining most named things.)You also need a syntax for mutating assignment. You can define a separate operator for that (like `:=`). Then there is the question of equality. From math, `=` is the natural notation because the operator there is often overloaded as an equality predicate.
Now you're in a funny spot. Declaring a variable and assigning to it later are semantically very similar operations. Both ultimately calculate a value and store it in memory. But they have different syntax. Meanwhile, defining a variable and testing two expressions for equality use the same syntax but have utterly unrelated semantics.
Given that math notation has grown chaotically over hundreds of years, it's just really hard to build an elegant notation that is both familiar to people and consistent and coherent.
x ← x + 1
Not familiar, perhaps understandable.Programming is telling things to the computer, and in this case, you’re telling it what x is. Whatever you tell a computer is all the computer knows, whatever a computer does can only be what it’s told. If you never told it what x was, then x wouldn’t be anything… that’s the truth.
This is the key point. Some people have a mental model that algebraic syntax is describing a set of immutable properties. You are defining things and giving them names, but not changing anything. There is no notion of time or sequence, because the universe is unchanging anyway. All you're doing is elucidating it.
Then there is a model where you are molding the state of a computer one imperative modification at a time. Sequence is essential because everything is a delta based on the state of the world before.
You have the latter model, which is indeed how the hardware behaves. But people with a mathematical mindset often have the former and find the latter very unintuitive.
Look, I teach IT (to both novices and interested folks at a college) for a living; count this idea as one that, when I present it this simply, many a lightbulb goes on for those new to programming. Much like for zero-indexed arrays, I do very well with "look, this is stupid, but here's why it got that way, we'll just deal with it."
And while on occasion I take pride in nerd-dom, I feel like -- especially with the advent of AI for coding -- this is dinosaur stuff, where we would do better to go along with what's WAY more intuitive than to try to stick with mathematical or programming purity, etc.
I must go dig up the Erlang book from my library. As I recall, it was a great read.
And they were right, rebranding was all Erlang needed 13 years ago
EDIT: there is Lumen, but not sure if it's stalled or still going.
It is not immediately clear what the intended usage pattern for Lumen and WebAssembly is.
Pros and Cons
Things we like:
The idea of having both runtime and code compile is cool
Things we’re not big fans of: We could not immediately figure out exactly how Lumen works, and builds appear to be failing
The project might be stalled or unmaintained. It has not been updated in over a year.Erlang/OTP already solves that — beautifully.
So, the motivation is:
“What if BEAM’s concurrency runtime could itself be compiled to WebAssembly — and become the actor system of the WebAssembly world?”
That’s why projects like Firefly and Lumen are interesting: they’re exploring whether Erlang’s runtime model can become part of the WASM ecosystem — just like how Go and Rust shaped the serverless world.
A ten-second search reveals [0]. (Have Kids These Days forgotten all about Emscripten?) However, given that web browser pages are often short-lived, I don't see what benefit bringing in all of Erlang and its VM gets you, other than the fact that you've pulled off the stunt.
[0] <https://www.erlang.org/doc/system/expressions.html#guard-exp...>
Gleam is very much worth checking out. It's syntax is very nice and natural feeling.