Hacker News new | past | comments | ask | show | jobs | submit login
Clojerl – Clojure for the Erlang VM (github.com)
309 points by tosh 28 days ago | hide | past | web | favorite | 100 comments

That’s very cool. I’ve added Clojerl to my list of alternative languages on the BEAM: https://gist.github.com/macintux/6349828#alternative-languag...

Given the extent to which the Erlang VM is optimized for immutable data, network transparency, and message passing, I can see why Clojure on the JVM and CLR would not have had the same success with the actor model as Erlang has.

I like your list, but one thing that would be helpful for me is in the alternative languages available on the BEAM, make the distinction between those implementations which are "BEAM languages" vs those that are simply implemented on the BEAM.

For example, Elixir is a proper BEAM language that targets the BEAM directly in a compile step.... but Luerl is not: Luerl is basically a Lua interpreter written in Erlang. I would expect different trade-offs from Elixir vs. Luerl as such. For example, I have a project where I need a limited, embedded scripting environment inside of an otherwise Elixir project. Using a BEAM language seems to be difficult to impose the desired limitations for such scripting environment, but in Luerl it seems I can do just that... limiting the scripting to a-less-than-system-wide scope. Of course... I expect a fairly substantial performance penalty for that... but trade-offs :-).

I think if I were running this as a repo with the possibility of pull requests I’d get more granular, but I can rarely be bothered to do much more than occasionally add a link.

To be pedantic, btw, Elixir compiles to Erlang Abstract Format, not the BEAM itself.

Benchmarking Clojure (both JVM and JS) vs Erlang immutable data structures would be very interesting given the focus on clever implemeations (persistent data structures) on the Clojure side and the VM level specialization on the Erlang side.

> I’ve added Clojerl to my list of alternative languages on the BEAM


As a bit of a shameless plug, I have an entry for your list: https://otpcl.github.io/ (GitHub repo: https://github.com/otpcl/otpcl)

I don’t ...

The JVM is a kitchen sink environment. The BEAM is very opinionated. I would expect the VM built from the ground up to support a specific programming model to be superior at doing just that.

BEAM is a wonderful VM, but calling it "optimized" for anything is problematic. It has focused on certain use cases, but it's seen less than 1% of the investment in the JDK, so I guess it's better to call it "specialized". While it works well enough for many things, its performance is like the JVM limping on both legs after a terrible car accident and a bad case of pneumonia while trying to walk on an icy road. You are correct, though, that it probably performs better than a general-purpose platform with a similar level of investment.

I think your statement goes too far. In my experience, it's very difficult to do lightweight threading on the JVM anywhere near the performance of the BEAM, as well as region allocation in the style used by high-performance Erlang programs. I think a comparison is unfair. The BEAM definitely sucks for compute-oriented tasks, but it's an immense amount of work to make a JVM-based program compete in the areas where it's good.

Yeah, but lightweight threading is a built in primitive in BEAM, so if you only measure scheduling overhead it is very low, but once you do any work inside those processes, it runs like any code running on low-performance runtimes. The isolated heaps are also OK, but the modern JVM GCs would still give you lower latency even with a shared heap. BEAM, CPython, MRI Ruby and other low-performance runtimes get the job done for whatever it is they're used for, and if all you're doing is IO it may not be too bad, but let's not mention those runtimes anywhere near good performance. BEAM is certainly in the bottom half or third of the Techempower benchmarks.

yeah each individual process has low resource allocation. There could be millions running on the same box so that makes sense.

Luckily, computational parallelization is not a big challenge with new libraries such as: https://github.com/plataformatec/flow

However, immutability might still become a challenge in terms of resources/performance. Rust is often used to patch that with Erlang's NIF.

Don't forget Fibers - coming to a JVM near you soon!

Hard for him to forget that -- take a look at who you're responding to.

BTW, many years ago, the author of Erjang told me that eventually Erjang will be faster than BEAM for running Erlang apps, b/c of all the investment that went into the JVM ecosystem. I'm not sure it's the case now (probably since nobody using Erjang in production).

You are correct in describing the raw performance of BEAM, but I'm not sure it's relevant for a typical IO-bound Erlang/Elixir app. Also most large real-life apps would use NIFs written in a language capable generating native code, i.e. C/C++ or Rust.

There is no doubt that JVM can provide massively better performance for a lot of stuff, but I wouldn't be suprised if Beam kicked JVM's butt in at least some areas.

It's pretty much the only system I know of that provides for massive numbers of fairly scheduled, preemptive green threads. To do so it makes trade-offs that are not generally attractive, but I'd be surprised if it didn't beat the JVM here.

I would be. BEAM is just a very slow platform, not just compared to Java, but also compared to JavaScript and Go. Again, that's not to say it's not very useful for some things (although many Erlang apps are really mixed Erlang/C apps because of BEAM's performance). Hey, CPython is really slow, too and yet very useful.

Green threads is another matter as it's not a feature that currently exists on the Java platform (there are somewhat similar features in Java platform languages like Kotlin's coroutines), but there is currently a project (that I'm leading) to add fibers (AKA user-mode threads, AKA lightweight threads, AKA green threads) to the JVM: https://wiki.openjdk.java.net/display/loom/

It's true that BEAM has excellent concurrency, parallelism, supervision, message passing... but I don't know understand why that has to come at the expense of being terrible at everything else. Why doesn't it have even a baseline reasonable quality JIT? Why doesn't its GC use a design more recent than half a century ago? It's got big corporate backers and PhDs working on it.

I would imagine that's because they'd rather focus whatever resources they have on the needs and priorities of their target audience, which probably don't think performance is critical. I hope that one day TruffleBEAM+Loom would be a great platform for all those wonderful Erlang apps.

Searching for TruffleBEAM+Loom doesn't yield any meaningful results. Could you provide any info about what it is?

It's something that I hope would exist one day. Loom is a project that I'm working on to add lightweight threads to the Java platform (https://wiki.openjdk.java.net/display/loom/) and Truffle is a framework that allows writing fast language runtimes for the Java platform or standalone that chrisseaton is working on (https://github.com/oracle/graal/tree/master/truffle).

> Why doesn't it have…

Perhaps because it wasn't intended to be used for everything —

"What sort of problems is Erlang not particularly suitable for? … Most (all?) large systems developed using Erlang make heavy use of C for low-level code, leaving Erlang to manage the parts which tend to be complex in other languages, like controlling systems spread across several machines and implementing complex protocol logic."


This seems like an argument being made backwards.

> Most (all?) large systems developed using Erlang make heavy use of C for low-level code

But they use C... because Erlang is too slow. Erlang isn't slow because they use C.

This is actually an argument for the need to make Erlang faster - we've got proof it's not fast enough for what they want to do!

And the worst thing is that when you start to use C code it's them a self-fulfilling prophecy - you can't optimise your Erlang code because it's now lots of calls to native code. I wrote my PhD on this problem.

Seems like an intentional separation of concerns.

> But they use C... because

They use C because they think it's a good tool for some things.


> But they use C... because Erlang is too slow. Erlang isn't slow because they use C.

Erlang can and does focus on solving problems like distribution, concurrency, and managing high-level issues in distributed concurrent systems because speed within a single sequential task is an adequately solved problem, and the existing solution can be leveraged in systems using Erlang for higher-level concerns.

So, no, it's not wrong to say Erlang is slow because of the use of C for speed in Erlang systems.

Isn't that how all scripting languages became viable, they provided fast C extensions where it mattered the most. I.e. dropping to C for performance is by design.

Yes it made sense at the time. But now look at Ruby where they're trying to add a better GC and JIT because people want more speed - they're severely restricted in their options by the design of the C extension API.

"but I don't know understand why that has to come at the expense of being terrible at everything else."

A great deal of it is certainly just resource poverty compared to the JVM or the various JS runtimes. It may have some nice high-powered resources dedicated to it, but I'm still very comfortable with pron's assessment that the JVM has literally 100x more resources poured into it.

There are also some decisions that I would consider suboptimal for performance in the original Erlang specification though:

1. It extensively uses linked lists as a data structure. It was very fashionable in functional programming at the time, but the performance impact has in relative terms gotten worse as CPUs continue to speed up relative to RAM. Erlang does recover some of this vs. other functional programming languages in that the process model tends to keep the linked list components closer together together in RAM because they'll stay in the process' arena rather than being spread arbitrarily out over RAM, so walking a linked list a couple times is at least very likely to fit well into L1, but this is still going to be a pervasive loss of performance.

2. Haskell has done a lot of work in how to reconcile immutability with performance, and I'd still say there's a penalty there. Erlang hasn't, and a lot of it wouldn't apply (Erlang is strict), so you're still getting ~1980s/1990s+whatever optimizations we could add performance on a lot of the immutable stuff. It does do some of the obvious optimizations like rewriting obvious recursive algorithms to use mutability internally, but in general you're still going to pay some penalty here.

3. This one may be a bit controversial, so let me first say I deeply respect Erlang as a design, consider it to have been very far ahead of its time, and that given the general understandings of programming language theory at the time, that Erlang is a staggering accomplishment. That said, with the benefit of decades of hindsight on the design, the Erlang type system is deeply suboptimal. From what I can see, the primary purpose of the design is to ensure that you can't pass references between processes so that there's no way to modify a process' memory from another. The way it accomplished this is with a type system that has no references in it. But because this matter wasn't as well understood then as it is now, it also overcompensated with making everything immutable, removing all ability to have custom user types, and yet at the same time, having a fully dynamic type system in which there is only one type: "Erlang term". It's not necessary to kill all custom user types; you can just kill the things that make them unable to be passed across the network, which isn't everything. You don't need to make things immutable, you just need to ensure that references can't be passed. You don't need to make everything dynamically typed so that you don't have to synchronize definitions of those types; there are other ways that this can be dealt with. There's just a lot of these little things where one could finesse the result but the Erlang design hits it with a sledgehammer.

There's a case to be made for that, too. A lot of the finessing would be a lot more complicated (e.g., Rust does a lot better job with managing mutability than Erlang, but look at the complication in the type system as a result; it doesn't come for free.) As language design goes, there's a lot of room for debate.

But in terms of the performance impact, Erlang ends up with the worst aspects of dynamic typing on performance, and with not all that many of the benefits of dynamic typing. (You get some. There's more dynamism than initially meets the eye in Erlang. For instance, where you say lists:append(L1, L2), lists and append are just atoms. You can say L = lists, A = append, and then run L:A(L1, L2), and do conditionals on that, etc. It took me a long time to learn that. But you still miss out on a lot of the dynamism of dynamic languages, and even what there is is often harder to manage. And also, you pay in the performance for this, too.)

An Erlang written for the modern era, but tuned a lot more for performance, isn't Go. But Go is probably close enough to inhibit success for any such effort; I observe that languages tend to inhibit the creation of things very close to where they are, but not the same. (Bizarrely, it seems to be easier to create something that is essentially a clone of a current language from a programming language theory perspective with an opinionated syntax gloss on it than to create a language that is mostly like another but with a couple of important PLT changes. I don't think I fully understand why this is, but the observation seems pretty solid. So, "Go + full process isolation" is unlikely to attract enough support to succeed, even though I'd personally love to see it.)

I appreciate the work you are doing on Loom. As someone who has done production Erlang code in the past and presently has to code in Java, I eagerly await the day that Loom becomes production ready.

What are your thoughts on Pony (https://www.ponylang.io/)?

I just saw a couple of talks about it. Seems very interesting (more interesting to me than Rust), but I think it's too opinionated to gain much attention in this climate.

> Seems very interesting (more interesting to me than Rust)

My sentiments as well.

> I think it's too opinionated to gain much attention in this climate

Possibly. Rust is pretty opinionated but it seems to be doing well. My feeling is that Pony's probably not going to "win" (i.e. be the main replacement for C/C++) but I'm hoping that, like Erlang, it's able to carve out a stable enough niche.

There’s Akka. Also Scala has Future’s. Both are very similar to green threads.

I'd say the feature of BEAM is fault-tolerant massive scalability of concurrency rather than performance/throughput. JVM as a platform lacks all the concurrency tooling of BEAM like the integrated debugging and monitoring tools. The AKKA implementation seems like a total afterthought rather than the fundamental core which it is in Erlang.

Moreover, from what I understand unlike BEAM, JVM does not prioritize low consistent latency but throughput instead.

I just feel they're designed for very different purposes. BEAM is most definitely not a general computing platform and would not perform well as such. In contrast, I'd imagine it'd be painful to develop concurrent stateful distributed systems on top of the JVM, regardless of the language.

> In contrast, I'd imagine it'd be painful to develop concurrent stateful distributed systems on top of the JVM, regardless of the language.

Concurrent stateful distributed systems on the Java platform probably outnumber those on BEAM 100 to 1, but I agree that we absolutely love Erlang's relevant constructs, which is why we're bringing them to the Java platform.

IIRC, Kilim (a Java library) performed better than Erlang in benchmarks.

In addition, every library written for the BEAM in any language is designed for message passing and the actor model. Clojure would not have that advantage on the JVM.

Clojure doesn't use the actor model...

Which was part of the discussion at the linked article.

Oh okay, sorry I misunderstood your comment the first time.

The rationale for why Rich Hickey didn't go for the actor model are actually documented here: https://clojure.org/about/state

I agree with you, that the JVM also would have probably made it more difficult to incorporate and leverage, though Scala seems to have pretty successfully done that, and Fantom has gone that route as well successfully (though the language is niche) on the JVM. So I'm not totally sure either.

Interesting! I posted Erjang (JVM based Erlang VM)[0] a few days ago, I guess I missed this one. I have a fascination with both Erlang and Lisp. I love Erlang because it is definitely a back-end language. I also love it's resiliency. I like how expressive Lisp languages can be. So maybe we'll just run Clojerl on top of Erjang, which is on the JVM, and Clojerl is based on a JVM language, talk about an onion.

[0]: https://news.ycombinator.com/item?id=20174830

Putting an Erlang-like language on the JVM would really lose all the advantages of Erlang, wouldn't it. The syntax, while very useful, isn't the real strength of the language. It's the BEAM.

It looks like this is actually running the real Erlang/OTP, just with some amount of performance penalty from not being on the BEAM. This could be fantastic for fans of BEAM languages who now have a low-profile way to introduce, say, an Elixir proof of concept into a JVM-dominated infrastructure.

Would it really matter though, whether the underlying VM is JVM or BEAM, if people don't want to code in Erlang or Elixir?

I don't think introducing the BEAM is the hard part, I think it's all about the language barrier.

Personally I spent most of my learning curve on the BEAM facilities rather than Elixir itself. Elixir as a language is simple and fairly imperative, it's quick to pick up.

Using the language for data transformations and such is a breeze but learning the concurrency primitives, message passing, OTP tooling and behaviors is where the real work is in my opinion, when building distributed systems on top of BEAM.

In my experience the opposite is true.

I've been able to introduce the BEAM in a large company (where I work) but the barrier has been they don't know it, they know very well the JVM and they don't care about the language if it can produce a runnable jar.

I would really use the JVM more if I could program it in Elixir.

This is brilliant.

I'm a shallow Clojure user, I like Clojure but every time I look into 'modern' Clojure code base I would see a lot stuartsierra/component. I know this is quite a library with high quality, but it's more like a sign of compromise - 'we still need stateful component eventually, although we already have 5 different ways to deal with the state, we need another one'.

Despite what Rich said about Actors, the state in Erlang/OTP is more well-modeled. The state(process mechanism) is not only playing well with immutable functional languages but also much more robust than OO languages. And it also largely simpifies the mental model - it removes the need of atom/agent/variable/object, etc.

Another neat thing, of course, no awkward loop/recur anymore.

i especially like the QA section explaining "why do it if Hickey said actors are bad" (intentional strawman there):

> The points he makes are of course very good. For example, when no state is shared between processes there is some communication overhead, but this isolation is also an advantage under a lot of circumstances. He also mentions here that building for the distributed case (a.k.a processes and message passing) is more complex and not always necessary, so he decided to optimise for the non-distributed case and add distribution to the parts of the system that need it. Rich Hickey calls Erlang "quite impressive", so my interpretation of these writings is that they are more about exposing the rationale behind the decisions and the trade-offs he made when designing Clojure (on the JVM), than about disregarding the actor model.

That would be my understanding as well. Clojure and Erlang are ideologically quite close, just made with slightly different purposes. Erlang - to be distributed from the ground up. Clojure - to handle mutability on somewhat lower level and be on JVM, where mutability is the norm.

How does Clojerl compare to Lisp Flavored Erlang (http://lfe.io/)? LFE looks like a quite mature project and it maps Lisp directly to BEAM. Interestingly, LFE has a collection of Clojure-like macros (https://github.com/rvirding/lfe/blob/develop/doc/lfe_clj.txt).

You should play with them both, and see what you like more. I don't feel like one is objectively "better" than the other, it's mostly a matter of preference.

I personally like LFE a bit better, because of the more-direct mappings to BEAM (as you mentioned). Lisp-Flavoured-Erlang is a very honest name; it feels like you're writing Erlang, just a nice and consistent Lisp syntax.

That said, I think Clojerl is pretty neat. I tend to find Clojure's macro syntax a bit cleaner than LFE's Common-Lisp style (I still get tripped up on commas). Also, Lisp-1 semantics are a lot more reasonable...I still hate putting `funcall`s everywhere.

Sorry for the off topic.

Any good recommendations for a Clojure book for a seasoned programmer but with little exposure to Lisps?

I taught myself Clojure with [Clojure for the Brave and True](https://www.braveclojure.com). It's a silly (free) online resource. I grew up learning Common Lisp and Scheme, and it was really easy for me to get into. That just meant I skipped the first chapter. It quickly got into doing things the Clojure Way™ and how to leverage its strengths. Highly recommended.

I second this resource, it's well explained and was also concise enough so that I actually finished it. Definitely covers the the important bits and a lot of advanced bits like macros and atoms, etc.

Joy of Clojure is my favorite whirl wind tour of the language. I generally suggest also pairing it with Clojure Applied, which deals with the larger "assembling the pieces into a whole" side of things.

Getting Clojure by Russ Olsen. It's the most recently published of the introductory Clojure books and imo the best written.

I bought Clojure in Action and The Joy of Clojure , both from Manning. I found Clojure in Action to be better suited to me as I too had little exposure to Lisps. Everybody raves about Joy of Clojure but it did not work for me. But now my favourite book is Clojure for the Brave and True -- it is awesome and fun.

I am thinking the onerous part of learning to use Clojure is not the lisp parts but the Java/JVM part, to the point I felt, if one is new to Java/JVM it is very difficult to use Clojure.

That is a great book, but it doesn't introduce the language at all.

Any initiative like this (language on top of the Erlang VM) with static typing out-of-the-box?

I really want to love Elixir but dynamic typing is a NO for me.

There's Purerl for PureScript that compiles to Erlang. There's a maintained package set for Spago for the Purerl community.

Just use Erlang with Dialyzer. It's not quite as nice as a lanugage with types built-in, but if you're strict about using it, it does work. I won't code without it.

I have burned more time than I care to admit trying to decipher dialyzer output shenanigans. I love dialyzer when my code doesn't generate any errors, and the rest of the time I kind of want to cry.

Not sufficient, and not for Erlang, but Dialyxir has a `mix dialyzer.explain` command, which gives an example of code that might cause a certain error. Some errors I have been unable to reproduce and I welcome examples of code that would produce them, so PRs are welcome =). Here is what I say for no_return, for example [0].

I maintain a library for converting Erlang Dialyzer messages to Elixir (Erlex [1]) which I hope to one day be able to retire with a stronger Elixir/Erlang communication (AST instead of string communication, e.g., and direct diffs between types).

[0] https://github.com/jeremyjh/dialyxir/blob/master/lib/dialyxi... [1] https://github.com/asummers/erlex

Ah, neat. I didn't know about dialyzer.explain. Will most def investigate.

Yeah, it would be really nice if the function has no local return errors could be more specific.

GLEAM - its Ocaml + elixir

Thanks, added that to my gist.

Why would I use this over elixir?

From the readme of the project:

> Clojure is a Lisp and as such comes with all the goodies Lisps provide. Apart from these Clojure also introduces powerful abstractions such as protocols, multimethods and seqs, to name a few. [...] It is fair to say that combining the power of the Erlang VM with the expressiveness of Clojure could provide an interesting, useful result to make the lives of many programmers simpler and make the world a happier place.

Also, at this point Clojure is becoming a kind of nice foundational language with multi-host targets. So if you know Clojure, you can now leverage the JVM, various JS runtimes, the CLR, now also the BEAM, etc. So there's that too. So basically, to someone already knowing Clojure it's a nice way to have access to more platforms.

There are a bit different due to the host environment.

Btw, use the iOS version a lot to learn

Another reason might be the "cultural" aspects of Clojure, and their impacts on its ecosystem - in particular simplicity and stability are paramount, whereas the Elixir ecosystem seems to put more emphasis on immediate ease of use and elegance à la Ruby, at the cost of doing some "magical" designs which you tend to not see in the Clojure ecosystem.

How exactly is stability not paramount in Elixir? It runs in the BEAM.

Stability of the language itself is another factor though. Clojure does a really good job avoiding breaking changes in the language.

With the exception of a few project config settings whose legacy variants are still backwards compatible, Elixir is absolutely stable as well.

So not sure what were you saying about Elixir.

If you want a Lisp (although there are multiple Lisps for the BEAM). If you want to help build a new language. If you don’t like Elixir’s syntax (raises hand).

Just curious--what don't you like about Elixir's syntax?

I don't particularly care for the ambiguity that stems from facets of it being optional, nor the way function match arms are defined, nor the :atom or lowercase variable naming syntax. The mixing of do and -> kinda bugs me as well. :shrug:

Though my opinion on the matter is deeply colored and probably unreliable because I'm one of those weirdos that thinks that Erlang syntax is actually quite nice for the most part.

Also, I'm in no position to complain since currently my technical life (what little is left not making slide decks) now revolves around Rust, Agda, and TLA+ (god help me).

I’m also one of those weirdos. I’m a big fan of Erlang syntax: very concise, mostly trivial to read (although list comprehensions can get hairy).

Same here. I’ll take Erlang’s conciseness and readability over Elixir’s prolixity any day.

It's been a while since I looked at Elixir but the different syntax for invoking named functions vs lambdas really left a bad taste in my mouth...

Also I remember trying to do something with the pipe operator that I couldn't get working due to the syntax of the language but which would've been trivial in Clojure using one of the threading macros.

Pardon me for saying it but it sounds like you tried for 5 minutes, gave up because it's not familiar to you, and then said you don't like the pipe operator.

You might have wanted to say something else but this is how you sounded to me. Am I wrong?

I think the more interesting question would be why Clojerl over LFE (http://lfe.io/)?

Yes, there is a community around Clojure that would feel more at home with the BEAM if they could use Clojure there... and this is likely the answer to my first sentence... but once you get to a Lisp it seems like the leap is less far to another Lisp and LFE, I would think, is better established.

So I guess the real question would be, for those outside the Clojerl project, are the benefits Clojure more specifically on the BEAM worth the costs of foregoing a (possibly/likely) more mature Lisp that already exists for the BEAM?

I can think of a few reasons: same language between front and backend, extensive standard library, repl driven development, simplicity, brevity, spec.

With Phoenix + LiveView maybe you won't need the frontend.

It’s a great project, but I doubt it’ll ever reach the maturity and functionality of Reagent, Om, Rum. Fulcro, Datascript, re-frame and Hoplon.

I wouldn't bet against Chris McCord and Jose Valim.

They've done a wonderful job with Phoenix and Elixir. I think this feature liveview will be develop as good as presence feature and eventually will be good enough.

it's such a weird concept to me.. "server-rendered html" is what i was doing most of my webdev career and suddenly it's the "hot new thing"?

anyway i still don't see why i would need it with Clojure if i can have single codebase and language for backend and frontend and render whatever i want at either -end.

Because with LiveView you can throw away 90% of your JavaScript and work almost exclusively with Elixir both on the frontend and the back end.

Right, but I could also throw away 100% of my JavaScript and not have to deal with any of the nodejs/npm/webpack/whatever nonsense if I used Clojure.

Clojure is incredibly popular, and there are probably lots of people that are interested in learning Clojure but scared away by the JVM ecosystem.

There’s no way either statement you’re saying ia true. Clojure is certainly not “incredibly popular.” And if you think many people are scared away from the JVM vs the BEAM, I don’t even know what to say.

Interesting. I'd really like to see Pytherl. Use the easy-to-learn Python syntax, as best as possible, but on the BEAM. I think that would be even better than Elixir for getting people on board.

I mean, at that point the only difference with Elixir is that you want whitespace delimited blocks over using DO/END.

Otherwise, none of the Python semantics make any sense on the BEAM, so I'm not sure that's that helpful, but who knows.

I doubt this is quite what you are looking for, but https://github.com/fazibear/export provides simple Elixir/Python interop.

You might like Reia.


Sadly it seems like all work on it has been stopped and they recommend using Elixir instead.

Love how puns are the go-to in CS

Good fit, but I think Elixir already _is_ Clojure on BEAM in spirit (sans Lisp syntax).

How true is that?

Registration is open for Startup School 2019. Classes start July 22nd.

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