Hacker Newsnew | past | comments | ask | show | jobs | submit | sam-cop-vimes's commentslogin

I'm almost wishing for the next major outage just so I can see this working :-)

It's been sitting on my shelf for a few years now. I take it out and read a couple of pages each time and then put it back. Keep thinking I should buy a guide to reading this book but never got around to it.

Even a short summary of the Wake can suffice to get you started. You're never going to understand it all, and that's okay, but even a brief chat with a Wake fan can give you the basic clues of its structure and the HCE/ALP Shem/Shaun dualities. I think it's a mistake to spend time with guidebooks than with the text itself if you want to read it for pleasure as opposed to writing a thesis on it. At least, postpone the guides until after your first trip once around.

This is exactly what we've decided we should do next time. Unfortunately we didn't generate an API token so we are sitting twiddling our thumbs.

Edit: seems like we are back online!


Took me ~30 minutes but eventually I was able to log in, get past the 2FA screen and change a DNS record.

I surely missed a valid API token today.


I'm still trying.

Still can't load the Turnstile JS :-/


Turnstile is back up (for now). Go refresh. I just managed to make an API key and turn off proxied DNS.

install tweak chrome extension and mitm yourself and force the js to load from somewhere else

Im able to generate keys right now through warp. Login takes forever but it is working.

What a well written article! Nothing complex is built overnight, so it is interesting to see how their defenses have evolved to their current state. Requires an engineering team which actually cares about all this and consistency of approach across what seems like 6 years? Impressive.

Thank you.

I feel the same - a lot of negativity in these comments . At the same time, openai is following in the footsteps of previous American tech companies of making themselves indispensable to the extent that life becomes difficult without them, at which point they are too big to control.

These comments seem to be almost a involuntary reaction where people are trying to resist its influence.


It's a bit rich for openai to claim they are protecting user data from journalists. Laughable, at best.

I can totally relate to this. Programming in Erlang felt so natural compared to the knots I was twisting myself into writing C++. I was churning out C++ code, but wasn't having fun. Suddenly Erlang made it fun and programming became addictive.

> Suddenly Erlang made it fun and programming became addictive.

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?


I'll try and answer this.

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.


It’s a subjective thing, but when a language clicks for you, work becomes pleasant. You get into (and maintain) a flow state. It feels as if you’re crafting something beautiful and elegant and simple. It’s the same reason people love painting, drawing, or sculpting with one specific medium over an other. They just like the aesthetic and process better.

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.


It's a bit like cutting wood. Cutting wood can feel terrible. You do it every day because you have to. Along the grain, in wet wood, with a handsaw.

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.


Until you hit a knot in the wood and get kickback, which leads to exciting times... j/k I get what you are trying to say.

Solving problems I guess. Have you used painful languages before? Imagine doing that, then discovering one that wasn't getting in your way all the time. It's easier to do things that are difficult in other languages. You can do so much on the BEAM, and you don't have to waste your time with thread pools or other nonsense.

The ability to load recompiled code on running processes makes it possible to change live services on the fly. I worked for a low budget mobile operator in SE-Asia where there were no test platforms, and every change was on the live servers. Erlang made changes fast, as small changes were trivial, while large changes were broken down into small changes, implemented individually, and tested. Rolling back was fast, as I kept the original code before modifying. No convoluted build structures, and praying the rollout to production doesn't throw unexpected errors.

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.


Everyone talks about GenServers and OTP and all that, and that part is great, but what sells it for me is that it's a practical functional programming language. You get 80% of the FP part of Haskell but you don't have to mess with monads. It has tail call optimization which makes it easy to write functions in general, one "function" is made up of several that call each other, much easier to reason about and write. In general code I use what I call the "holy trinity", atoms, tuples and pattern matching.

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.


For me, strictly immutable and side-effect free programming was a forcing function* to make me really decompose problems into isolated parts. Only when I could do that could I truly say I understood the problem (and its distinct sub-problems) in full.

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.


when I program, I am visualizing the machine I am building in my head. some language semantics are cleaner than others, allowing the bits and pieces to flow together more naturally, composing in elegant ways that do not require pointless effort be spent manually wrangling footguns and minutia.

Every coder has parts of programming they love, and parts they hate. Additionally, they have a mental model of what is risky, and what isn't. Languages, by their design, will make some things easier and some things harder, and so when people "love a language," they typically mean "it maps to what gives me dopamine."

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.


For me, it was Elixir pattern matching + GenServers + SupervisionTrees + Let It Fail mentality.

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.


For me (and I've been writing Elixir for probably a decade now...) Joe Armstrong's post here encapsulates it pretty well: https://joearms.github.io/published/2013-11-21-My-favorite-e...

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.


Ha, Ha! You and me both.

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.


Pattern matching and function guards sold me. I'll never look back, you can take patterns out of my COLD DEAD HANDS!

It's kind of like this:

https://xkcd.com/224/

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.


> https://xkcd.com/224/

> “My God, it’s full of ‘cars’”

Classic


You ever get a fresh pair of sharp scissors or a new very good knife? It feels like that.

> WHAT IS IT THAT YOU PEOPLE SEE!?

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.



Indeed - and break times don't seem to be very long. "fifteen minutes for coffee and then half an hour for lunch" - no time to waste on pleasantries when that is all the break you get!

This guy is amazing - the dedication to his craft is inspiring!


Super inspiring. A lot to read between the lines. Probably fairly introverted - prefers to be by himself than joking with coworkers. But not so much so that he can’t. He’s just really driven to be creative. And found a way, even though life took him down a very different path. “Let your wallet be your guide” is a good reminder that realistically there’s probably no chance he could make a living as a writer - very few can. But he made it happen anyway. Bravo!


Not really - if the market price for a crop is such that it depends on the greater volume which can be produced by GMO seeds, switching to non-GMO seeds becomes uneconomic.

Let's say GMO crops gives you a grain yield of 1-ton/acre and that non-GMO crops gives you a yield of 0.5-ton/acre. Now the market price is say set at $100/ton. This cuts down their earnings by half in the best case, all other inputs remaining the same.

Now if the GMO-seeds are controlled by a foreign entity, your entire agri output becomes dependent on that foreign entity not behaving badly. Whichever nation that controls the entity who owns the GMO-seed now has leverage over you.

So no, it isn't as simple as "switch back to using non-GMO seeds". This has to be carefully considered before adopting GMO-seeds.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: