My team was using Elm in production for about a year, but have been gradually replacing it with Typescript + React.
We started using it in version 0.18. We never bothered transitioning to 0.19 because there were a number of dependencies that weren’t being maintained, and we didn’t want to rewrite the functionality we were using from them.
The inability to install packages from anything but the official repo is a real pain. It made it really hard to reuse and modularize code. We had the choice of open sourcing anything we wanted to reuse, or adding extra steps to our build to copy files around.
There was also the problem of hiring and onboarding new team members. Like it or not, it’s far easier to hire someone to do front end work in Typescript than Elm. We developed some good tutorials for new team members to get started, but it still took more time to ramp up, since functional programming represents a big shift for a lot of people.
I really want Elm to succeed because it’s a joy to write, and the type system is incredibly helpful. But it will be a while before I recommend it to anyone for anything but fun projects.
Have you looked into Fable? Might have some of the benefits of Elm, but less restrictive and will interop beautifully with your TypeScript if you’re using Webpack.
.. think of it as a competitor to React or Vue, and is used to create websites and web apps.
This seems a bit shortsighted.
Debugging looks awful and is largely unhelpful
This is very true. After using Elm and some other things in the last couple of years, I’ve made the commitment to try and never use anything that doesn’t have good built-in debugging, and sane errors.
.. but that doesn’t work for our app so we can’t use it …
They mention this really casually, but it’s a well-known problem (and affecting us too).
You cannot install Elm packages from anywhere other than the official package repository.
This is technically true. A work around is to fork a project and import it in your elm.json.
What if you want a service worker in your app for offline support?
The author didn’t mention ports at all, which was surprising. There is the Process package for sort of this, and you can also use service workers via ports.
Anyway. I agree with some of the post (I’ve used Elm professionally for almost 2 years), and I’ve wondered what else is out there that’s a better Elm? Purescript? ReasonML? Something Clojure or Lisp based? Any suggestions?
I hadn’t written any Clojure (or any Lisp, really) before, so I did the simple HackerRank “counting valleys” question in Clojure and it was really nice. Having used Elm for the last while had me already in a functional mindset, which helped a lot.
I’m curious to get some feedback on my ~28 lines of Clojure as well, so I’ll see if I can find a willing soul to critique it.
I can be happy to critique, if you like. I’ve not worked with many other Clojure programmers, but I’ve read a bunch of code and have written a bunch as well.
That’d be nice! It’s only 27 lines of code, and solving the simple HackerRank question I mentioned, so it might be hard without the full context (the question). But anyway, I’ve put the code in a gist: https://gist.github.com/jesse-c/bd7605b53cb4cb9390192475514bf9fb
I have been exploring F#-to-JS with Fable, which has been surprisingly pleasant. For this project I also considered Elm and Purescript, but decided that Elm might be too foreign, and the company being a .NET shop made F# an easy choice over Purescript.
If you’re on Windows, that’s not a major issue. If you’re on a non-Windows platform, it might be slightly confusing to get started with – to the point of perhaps being worth it to look elsewhere.
Re installing packages: have you seen elm-git-install? Not a mature tool etc. but at least there’s an option.
A note about the Elm package catalog (it’s my project): it’s far from complete. There are ~1700 packages available, but the catalog is currently at 390. It’s probably not a fair indication of the breadth of the ecosystem (yet).
We had tried either that or something similar last year but had to move away from it some reason (vague, I know). At the moment we’ve gotten rid of all our forks, but if we have the need again, I’ll suggest it. Thanks!
Why? Elm’s tagline on its landing page says, ‘A delightful language for reliable webapps.’.
Any suggestions?
Do you want to stay with the Elm architecture but move to a more powerful, older and battle-tested language? Then check out bucklescript-tea. Do you want the benefits of the language with a more type-safe take on ReactJS? Try ReasonReact.
Summary: author’s expectations of a young language exceed the actual implementation, so they write a Medium article.
If you can’t tell: slightly triggering article for me, and I don’t use/advocate for Elm. I’d much prefer if the author either pitched in and helped, or shrugged and moved on to something else. Somehow, yelling into the void about it is worse to me, I think because there are one or two good points in there sandwiched between non-constructive criticisms.
The article provides valuable information for people considering using Elm in production. The official line on whether Elm is production ready or not is not at all clear, and a lot of people suggest using it.
I read “fastest” and “safest” as referring to “how fast can I can get work done” and “is this language a safe bet”, not fast and safe in the sense of performance. If that’s the right interpretation, then those conclusions flow naturally from the observations he makes in the article.
Right, the author made the same clarification to me on Twitter, so that’s definitely what he meant. In that sense, the conclusion is fine. Those are very ambiguous words though (I took them to mean “fastest runtime performance” and “least amount of runtime errors”).
TBF, I was a little too snarky in my take. I don’t want to shutdown legitimate criticism.
The official line on whether Elm is production ready or not is not at all clear, and a lot of people suggest using it.
That ambiguity is a problem. There’s also a chicken/egg problem with regard to marketing when discussing whether something is production ready. I’m not sure what the answer is.
It’s even more ambiguous for Elm. There are dozens of 100K+ line commercial code bases out there. How many should there be before the language is “production ready”? Clearly, for all those companies, it already is.
Perhaps the question is misguided and has reached “no true Scotsman” territory.
That’s one reason why this topic is touchy to me: things are never ready until the Medium-esque blogosphere spontaneously decides it is ready, and then, without a single ounce of discontinuity, everyone pretends like they’ve always loved Elm, and they’re excited to pitch in and put forth the blood, sweat, and tears necessary to make a healthy, growing ecosystem. Social coding, indeed.
In a sense, everyone wants to bet on a winner, be early, and still bet with the crowd. You can’t have all those things.
I like your last paragraph. When I think about it, I try to reach the same impossible balance when choosing technologies.
I even wrote a similar post about Cordova once (“is it good? is it bad?”). Hopefully it was a bit more considered as I’d used it for 4 years before posting.
The thing that bothers me with the developer crowd is somewhat different, I think. It’s the attempt to mix the other two unmixable things. On one hand, there’s the consumerist attitude to choosing technologies (“Does it work for me right now? Is it better, faster, cheaper than the other options?”). On the other hand, there are demands for all the benefits of open source like total transparency, merging your PR, and getting your favourite features implemented. Would anyone demand this of proprietary software vendors?
I’m not even on the core Elm team, I’m only involved in popularising Elm and expanding the ecosystem a bit, but even for me this attitude is starting to get a bit annoying. I imagine it’s worse for the core team.
Hey, thanks for your work on Elm. I’m much less involved than you, but even I find the “walled garden” complaints a little irritating. I mean, if you don’t like this walled garden, there are plenty of haphazard dumping grounds out there to play in, and even more barren desert. Nobody’s forcing anybody to use Elm! For what it’s worth, I think Evan and the Elm core team is doing great work. I’m looking forward to Elm 1.0, and I hope they take their time and really nail it.
The author of this article isn’t pretending to be an authority on readiness, and claiming that they’ll bandwagon is unwarranted. This article is from someone who was burned by Elm and is sharing their pain in the hopes that other people don’t get in over their heads.
Being tribal, vilifying the “Medium-esque blogosphere” for acts that the author didn’t even commit, and undermining their legitimate criticisms with “well, some people sure do love to complain!” is harmful.
I’d like to push back on this. What is “production ready”, exactly? Like I said in another comment, there are dozens of 100K+ line commercial Elm code bases out there. Clearly, for all those companies, it already is.
I’ve used a lot of other technologies in production which could easily be considered “not production ready”: CoffeeScript, Cordova, jQuery Mobile, Mapbox. The list goes on. They all had shortcomings, and sometimes I even had to make compromises in terms of requirements because I just couldn’t make particular things work.
The point is, it either works in your particular situation, or it doesn’t. The question is meaningless.
Here are my somewhat disjoint thoughts on the topic before the coffee has had a chance to kick in.
What is “production ready”, exactly?
At a minimum, the language shouldn’t make major changes between releases that require libraries and codebases to be reworked. If it’s not at a point where it can guarantee such a thing, then it should state that fact up front. Instead, its creator and its community heavily promote it as being the best thing since sliced bread (“a delightful language for reliable webapps”) without any mention of the problems described in this post. New folks take this to be true and start investing time into the language, often quite a lot of time since the time span between releases is so large. By the time a new release comes out and changes major parts of the language, some of those people will have invested so much time and effort into the language that the notion of upgrading (100K+ line codebases, as you put it) becomes downright depressing. Not to mention that most of those large codebases will have dependencies that themselves will need upgrading or, in some cases, will be have to be deprecated (as elm-community has done for most of my libraries with the release of 0.19, for example).
By promoting the language without mentioning how unstable it really is, I think you are all doing it a disservice. Something that should be perceived as good, like a new release that improves the language, ends up being perceived as a bad thing by a large number of the community and so they leave with a bad taste in their mouth – OP made a blog post about it, but I would bet the vast majority of people just leave silently. You rarely see this effect in communities surrounding other young programming languages and I would posit that it’s exactly because of how they market themselves compared to Elm.
Of course, in some cases it can’t be helped. Some folks are incentivized to keep promoting the language. For instance, you have written a book titled “Practical Elm” so you are incentivized to promote the language as such. The more new people who are interested in the language, the more potential buyers you have or the more famous you become. I believe your motivation for writing that book was pure and no one’s going to get rich off of a book on Elm. But, my point is that you are more bought into the language that others normally are.
sometimes I even had to make compromises in terms of requirements because I just couldn’t make particular things work.
That is the very definition of not-production-ready, isn’t it?
Disclaimer: I quit Elm around the release of 0.18 (or was it 0.17??) due to a distaste for Evan’s leadership style. I wrote a lot of Elm code (1234 and others) and put some of it in production. The latter was a mistake and I regret having put that burden on my team at the time.
From what I’ve seen, many people reported good experiences with upgrading to Elm 0.19. Elm goes further than many languages by automating some of the upgrades with elm-upgrade.
FWIW, I would also prefer more transparency about Elm development. I had to scramble to update my book when Elm 0.19 came out. However, not for a second I’m going to believe that I’m entitled to transparency, or that it was somehow promised to me.
To your other point about marketing, if people are making decisions about putting Elm into production based on its tagline, well… that’s just bizarre. For example, I remember looking at React Native in its early stages, and I don’t recall any extensive disclaimers about its capabilities or lack thereof. It was my responsibility to do that research - again, because limitations for one project are a complete non-issue for another project. There’s just no one-size-fits-all.
Finally, calling Elm “unstable” is simply baseless and just as unhelpful as the misleading marketing you allege. I get that you’re upset by how things turned out, but can’t we all have a discussion without exaggerated rhetoric?
That is the very definition of not-production-ready, isn’t it?
Exactly my point: there is no such definition. All those technologies I mentioned were widely used at the time. I put them into production too, and it was a good choice despite the limitations.
From what I’ve seen, many people reported good experiences with upgrading to Elm 0.19. Elm goes further than many languages by automating some of the upgrades with elm-upgrade.
And that’s great! The issue is the things that cannot be upgraded. Let’s take elm-combine (or parser-combinators as it was renamed to), for example. If you depended on the library in 0.18, then, barring the invention of AGI, there’s no automated tool that can help you upgrade because your code will have to be rewritten to use a different library because elm-combine cannot be ported to 0.19 (not strictly true, because it can be ported but only by the core team, but my point still stands because it won’t be). Language churn causes ecosystem churn which, in turn, causes pain for application developers so I don’t think it’s a surprise that folks get angry and leave the community when this happens given that they may not have had any prior warning before they invested their time and effort.
Finally, calling Elm “unstable” is simply baseless and just as unhelpful as the misleading marketing you allege. I get that you’re upset by how things turned out, but can’t we all have a discussion without exaggerated rhetoric?
I don’t think it’s an exaggeration to call a language with breaking changes between releases unstable. To be completely honest, I can’t think of a better word to use in this case. Fluctuating? In flux? Under development? Subject to change? All of those fit and are basically synonymous to “unstable”. None of them are highlighted anywhere the language markets itself, nor by its proponents. I’m not making a judgement on the quality of the language when I say this. I’m making a judgement on how likely it is to be a good choice in a production environment, which brings me to…
Exactly my point: there is no such definition. All those technologies I mentioned were widely used at the time. I put them into production too, and it was a good choice despite the limitations.
They were not good choices, because, by your own admission, you were unable to meet your requirements by using them. Hence, they were not production-ready. Had you been able to meet your requirements and then been forced to make changes to keep up with them, then that would also mean they were not production-ready. From this we have a pretty good definition: production-readiness is inversely proportional to the likelihood that you will “have a bad time” after putting the thing into production. The more that likelihood approaches 0, the more production-ready a thing is. Being forced to spend time to keep up with changes to the language and its ecosystem is “having a bad time” in my book.
I understand that our line of work essentially entails us constantly fighting entropy and that, as things progress, it becomes harder and harder for them maintain backwards-compatibility but that doesn’t mean that nothing means anything anymore or that we can’t reason about the likelihood that something is going to bite us in the butt later on. From a business perspective, the more likely something is to change after you use it, the larger risk it poses. The more risks you take on, the more likely you are to fail.
I think your definition is totally unworkable. You’re claiming that technologies used in thousands upon thousands of projects were not production ready. Good luck with finding anything production ready then!
I’ve been working with Clojure for almost a decade now, and I’ve never had to rewrite a line of my code in production when upgrading to newer versions because Cognitect takes backwards compatibility seriously. I worked with Java for about a decade before that, and it’s exact same story. There are plenty of languages that provide a stable foundation that’s not going to keep changing from under you.
I am stating that being able to put something in production is different from said thing being production ready. You claim that there is no such thing as “production ready” because you can deploy anything which is a reduction to absurdity of the situation. Putting something into production and being successful with it does not necessarily make it production ready. It’s how repeatable that success is that does.
It doesn’t look like we’re going to get anywhere past this point so I’m going to leave it at that. Thank you for engaging and discussing this with me!
Thank you as well. As I said in another comment, this is the first time I tried having an extended discussion in the comments in here, and it hasn’t been very useful. Somehow we all end up talking past each other. It’s unfortunate. In a weird way, maybe it’s because we can’t interrupt each other mid-sentence and go “Hang on, but what about?…”. I don’t know.
This doesn’t respond to bogdan’s definition in good faith.
production-readiness is inversely proportional to the likelihood that you will “have a bad time” after putting the thing into production. The more that likelihood approaches 0, the more production-ready a thing is.
In response to your criticisms, bogdan proposed a scale of production-readiness. This means that there is no such distinction between “production-ready” and not “production-ready”. Elm is lower on this scale than most advocates imply, and the article in question provides supporting evidence for elm being fairly low on this scale.
Frankly, I don’t really want to have a discussion with you. I’m calling you out because you were responding in bad faith. You didn’t address any of his actual points, and you dismissed his argument condescendingly. The one point you did address is one that wasn’t made, and wasn’t even consistent with bogdan’s stance.
I disagree that the question is meaningless just because it has a subjective aspect to it. A technology stack is a long term investment, and it’s important to have an idea how volatile it’s going to be. For example, changes like the removal the of the ability to do interop with Js even in your own projects clearly came as a surprise to a lot of users. To me a language being production ready means that it’s at the point where things have mostly settled down, and there won’t be frequent breaking changes going forward.
By this definition, Python wasn’t production ready long after the release of Python 3. What is “frequent” for breaking changes? For some people it’s 3 months, for others it’s 10 years. It’s not a practical criterion.
Even more interestingly, Elm has been a lot less volatile than most projects, so it’s production ready by your definition. Most people complain that it’s changing too slowly!
(Also, many people have a different perspective about the interop issue; it wasn’t a surprise. I don’t want to rehash all that though.)
Python wasn’t production ready long after the release of Python 3.
Python 3 was indeed not production-ready by many people’s standards (including mine and the core team’s based on the changes made around 3.2 and 3.3) after its release up until about version 3.4.
Even more interestingly, Elm has been a lot less volatile than most projects, so it’s production ready by your definition. Most people complain that it’s changing too slowly!
“it’s improving too slowly” is not the same as “it’s changing too slowly”.
By @Yogthos’s definition, neither Python 2 nor Python 3 were “production ready”. But if we’re going to write off a hugely popular language like that, we might as well write off the whole tech industry (granted, on many days that’s exactly how I feel).
Re Elm: again, by @Yogthos’s definition it’s perfectly production ready because it doesn’t make “frequent breaking changes”.
By @Yogthos’s definition, neither Python 2 nor Python 3 were “production ready”.
Python 2 and 3 became different languages at the split as evidenced by the fact that they were developed in parallel. Python 2 was production ready. Python 3 was not. The fact that we’re using numbers to qualify which language we’re talking about proves my point.
It took five years for Django to get ported to Python 3. (12)
Re Elm: again, by @Yogthos’s definition it’s perfectly production ready because it doesn’t make “frequent breaking changes”.
You’re hanging on the wording here and “frequent” is not as important to Yogthos’ argument as “breaking changes” is.
I think most people agree that Python 3 was quite problematic. Your whole argument seems to be that just because other languages have problems, you should just accept random breaking changes as a fact of life. I strongly disagree with that.
The changes around ecosystem access are a HUGE breaking change. Basically any company that invested in Elm and was doing Js interop is now in a really bad position. They either have to stay on 0.18, re-implement everything they’re using in Elm, or move to a different stack.
Again, as I noted there is subjectivity involved here. My standards for what constitutes something being production ready are different than yours apparently. That’s fine, but the information the article provides is precisely what I’d want to know about when making a decision of whether I’d want to invest into a particular piece of technology or not.
I don’t think you are really aware of the changes to Elm because you’re seriously overstating how bad they were (“re- implement everything” was never the case).
I agree that there is useful information in the article – in fact, I try to read critical articles first and foremost when choosing technologies so it’s useful to have them. I never said that we should accept “random breaking changes” either (and it isn’t fair to apply that to Elm).
I still don’t see that you have a working definition of “production ready” – your definition seems to consist of a set with a single occupant (Clojure).
As an aside, this is the first time I’ve had an extended discussion in the comments here on Lobsters, and it hasn’t been very useful. These things somehow always end up looking like everyone’s defending their entrenched position. I don’t even have an entrenched position – and I suspect you may not either. Yet here we are.
Perhaps I misunderstand the situation here. If a company has an Elm project in production that uses Js interop, what is the upgrade path to 0.19. Would you not have to rewrite any libraries from the NPM ecosystem in Elm?
I worked with Java for around a decade before Clojure, and it’s always been rock solid. The biggest change that’s happened was the introduction of modules in Java 9. I think that’s a pretty good track record. Erlang is another great example of a stack that’s rock solid, and I can name plenty of others. Frankly, it really surprises me how cavalier some developer communities regarding breaking changes and regressions.
Forum discussions are always tricky because we tend to use the same words, but we assign different meanings to them in our heads. A lot of the discussion tends to be around figuring out what each person understands when they say something.
In this case it sounds like we have different expectations for what to expect from production ready technology. I’m used to working with technologies where regressions are rare, and this necessarily colors my expectations. My views on technology adoption are likely more conservative than majority of developers.
Prior to the 0.19 release, there was a way to directly call JS functions from Elm by relying on a purely internal mechanism. Naturally, some people started doing this, despite repeated warnings that they really shouldn’t. It wasn’t widespread, to my knowledge.
All the way in 2017, a full 17 months before 0.19 release, it was announced that this mechanism would be removed. It was announced again 5 months before the release.
Of course, a few people got upset and, instead of finding a migration path, complained everywhere they could. I think one guy wrote a whole UI framework based on the hack, so predictably he stomped out of the community.
There is an actual JS interop mechanism in Elm called ports. Anybody who used this in 0.18 (as they should have) could continue using it unchanged in 0.19. You can use ports to integrate the vast majority of JS libraries with Elm. There is no need to rewrite all JavaScript in Elm. However, ports are asynchronous and require marshalling data, which is why some people chose to use the internal shortcut (aka hack) instead.
So, if a company was using ports to interop with JS, there would be no change with 0.19. If it was using the hack, it would have to rewrite that portion of the code to use ports, or custom elements or whatever – but the rework would be limited to bindings, not whole JS libraries.
There were a few other breaking changes, like removing custom operators. However, Elm has a tool called elm-upgrade which helps to identify these and automatically update code where possible.
There were also fairly significant changes to the standard library, but I don’t think they were any more onerous than some of the Rails releases, for example.
Now, regarding your “rock solid” examples by which I think you mean no breaking changes. If it’s achievable, that’s good – I’m all for it. However, as a counterexample, I’ll bring up C++ which tied itself into knots by never breaking backward compatibility. It’s a mess.
I place less value on backward compatibility than you do. I generally think that backward compatibility ultimately brings software projects down. Therefore, de-prioritising it is a safer bet for ensuring the longevity of the technology.
Is it possible that there are technologies which start out on such a solid foundation that they don’t get bogged down? Perhaps – you bring up Clojure and Erlang. I think Elm’s core team is also trying to find that kind of foundation.
But whether Elm is still building up towards maturity or its core team simply has a different philosophy regarding backward compatibility, I think it’s at least very clear that that’s how it is if you spend any time researching it. So my view is that anybody who complains about it now has failed to do their research before putting it into production.
I feel like you’re glossing over the changes from native modules to using ports. For example, native modules allowed exposing external functions as Tasks allowing them to be composed. Creating Tasks also allows for making synchronous calls that return a Task Never a which is obviously useful.
On the other hand, ports can’t be composed like Tasks, and as you note can’t be used to call synchronous code which is quite the limitation in my opinion. If you’re working with a math library then having to convert the API to async pub/sub calls is just a mess even if it is technically possible to do.
To sum up, people weren’t just using native modules because they were just completely irresponsible and looking to shoot themselves in a foot as you seem to be implying. Being able to easily leverage existing ecosystem obviously saves development time, so it’s not exactly surprising that people started using native modules. Once you have a big project in production it’s not trivial to go and rewrite all your interop in 5 months because you have actual business requirements to work on. I’ve certainly never been in a situation where I could just stop all development and go refactor my code as long as I wanted.
This is precisely the kind of thing I mean when I talk about languages being production ready. How much time can I expect to be spending chasing changes in the language as opposed to solving business problems. The more breaking changes there are the bigger the cost to the business is.
I’m also really struggling to follow your argument regarding things like Rails or C++ to be honest. I don’t see these as justifying unreliable tools, but rather as examples of languages with high maintenance overhead. These are technologies that I would not personally work with.
I strongly disagree with the notion that backwards compatibility is something that is not desirable in tooling that’s meant to be used in production, and I’ve certainly never seen it bring any software projects down. I have however seen plenty of projects being brought down by brittle tooling and regressions.
I view such tools as being high risk because you end up spending time chasing changes in the tooling as opposed to solving business problems. I think that there needs to be a very strong justification for using these kinds of tools over ones that are stable.
The question isn’t even close to meaningless… Classifying something as “production ready” means that it is either stable enough to rely on, or is easily swapped out in the event of breakage or deprecation. The article does a good enough job of covering aspects of elm that preclude it from satisfying those conditions, and it rightly warns people who may have been swept up by the hype around elm.
Elm has poor Interop, and is (intentionally) a distinct ecosystem from JS. This means that if Elm removes features you use, you’re screwed. So, for a technology like Elm (which is a replacement of JS rather than an enhancement) to be “production ready” it has to have a very high degree of stability, or at least long term support for deprecated features. Elm clearly doesn’t have this, which is fine, but early adopters should be warned of the risks and drawbacks in great detail.
Let’s keep it really simple, to me ‘production-ready’ is when the project version gets bumped to 1.0+. This is a pretty established norm in the software industry and usually a pretty good rule of thumb to judge by. In fact Elm packages enforce semantic versioning, so if you extrapolate that to Elm itself you inevitably come to the conclusion that hasn’t reached production-release readiness yet.
The term “production ready” is itself not at all clear. Some Elm projects are doing just fine in production and have been for years now. Some others flounder or fail. Like many things, it’s a good fit for some devs and some projects, and not for some others – sometimes for reasons that have little to do with the language or its ecosystem per se. In my (quite enjoyable!) experience with Elm, both official and unofficial marketing/docs/advocates have been pretty clear on that; but developers who can’t or won’t perceive nuance and make their own assessments for their own needs are likely to be frustrated, and not just with Elm.
I agree that there’s valuable information in this article. I just wish it was a bit less FUDdy and more had more technical detail.
I think there’s an angle to Elm’s marketing that justifies these kinds of responses: Those “author’s expectations” are very much encouraged by the way the Elm team presents their language.
Which criticisms do you find unfair, which are the good points?
think there’s an angle to Elm’s marketing that justifies these kinds of responses
I’m sympathetic to both Elm and the author here. I understand Elm’s marketing stance because they ask devs to give up freely mixing pure/impure code everywhere in their codebase on top of a new language and ecosystem. (In general, OSS’s perceived need for marketing is pretty out of hand at this point and a bit antithetical to what attracts me to it in the first place). OTOH it shouldn’t be possible to cause a runtime error in the way the author described, so that’s a problem. I’d have wanted to see more technical details on how that occurred, because it sounded like something that type safety should have protected him from.
Fair criticisms:
Centralized ecosystem (though this is by design right now as I understand)
Centralized package repo
Official docs out of date and incomplete
Unfair criticisms:
PRs being open after 2 years: one example alone is not compelling
Tutorials being out of date: unfortunate, but the “Cambrian explosion” meme from JS-land was an implicit acknowledgement that bitrot was okay as long as it was fueled by megacorps shiny new OSS libs, so this point is incongruous to me (even if he agrees with me on this)
“Less-popular thing isn’t popular, therefore it’s not as good”: I understand this but also get triggered by this; if you want safe, established platforms that have a big ecosystem then a pre-1.0 language is probably not the place to be investing time
The conclusion gets a little too emotional for my taste.
Thanks for the detailed reply; the criticism of the article seems valid.
(As a minor point, the “PRs being open” criticism didn’t strike me as unsubstantiated because I’ve had enough similar experiences myself, but I can see how the article doesn’t argue that well. Certainly I’ve felt that it would be more honest/helpful for elm to not accept github issues/prs, or put a heavy disclaimer there that they’re unlikely to react promptly, and usually prefer to fix things their own way eventually.)
A lot of the things listed in the articles are things that have been explicitly done to make things harder for contributions to happen. The development of Elm has explicitly made choices to make things harder, and not in a merely incidental way.
This isn’t “the language is young” (well except for the debug point), a lot of this is “the language’s values go against things useful for people deploying to production”)
I don’t know, other than the point about the inability to write native modules and the longstanding open PR’s, all of the rest of the issues very much seem symptomatic of a young language.
The native module point sounds very concerning, but I don’t think I understand enough about elm or the ecosystem to know how concerning it is.
I’ve been vaguely following along with Elm, and the thng that makes me err on agreeing with this article is that the native module thing used to not be the case! It was removed! There was a semi-elegant way to handle interactions with existing code and it was removed.
There are “reasons”, but as someone who has a couple ugly hacks to keep a hybrid frontend + backend stack running nicely, I believe having those kinds of tricks are essential for bringing it into existing code bases. So seeing it get removed is a bit red flag for me.
I never relied on native modules, so I didn’t really miss them. But we now have ports, which I think is a much more principled (and interesting) solution. I felt that they worked pretty well for my own JS interop needs.
Stepping back a bit, if you require the ability do ugly hacks, Elm is probably not the right tool for the job. There are plenty of other options out there! I don’t expect Elm to be the best choice for every web front-end, but I do appreciate its thoughtful and coherent design. I’m happy to trade backward compatibility for that.
If you spend any amount of time in the Elm community you will find that contributions to the core projects are implicitly and explicitly discouraged in lots of different ways. Even criticisms of the core language and paradigms or core team decisions are heavily moderated on the official forums and subreddit.
Also how are we using the term “young”? In terms of calendar years and attention Elm is roughly on par with a language like Elixir. It’s probably younger in terms of developer time invested, but again this is a direct result of turning away eager contributors.
I think it’s fine for Elm to be a small project not intended for general production usage, but Evan and the core team have continually failed to communicate that intent.
I have not used elm, and have no opinion either way. But this strikes me as wrong:
No, it’s not worth it. I prefer a language whose design approach isn’t rooted in an inherent distrust of its users.
There’s a quote I rather like: “UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things”.
Take something like monkey patching in Ruby or Python: I’ve definitely used it on 2 or 3 occasions where it helped me to fix a problem that would otherwise be hard to fix, for example to work around limitations in the stdlib.
But on the other hand, I’ve also seen people use it for no reason in particular, where it was clearly not needed.
Great power comes with great responsibility, and it’s been demonstrated many times that programmers will abuse power given to them. Giving users all the power is a perfectly valid choice, but does come with trade-offs, and this is also true for not giving power to users.
Phrasing it as “distrust of users” strikes me as an unconstructive way to have a conversation about this.
Pull requests being open for 2+ years
It’s really unfortunate when that happens, but it happens. I think I’ve seen it in almost all non-trivial open source projects.
If it’s really important for you, then friendly asking again after a few weeks (maybe on chat or mailiing list, rather than GitHub) often helps.
Of all the points mentioned in the article, the only one I consider a real issue is the fact that Elm is the most closed-source open source project I’m aware of.
I used Elm for ~2 years, really enjoyed it. Felt infinitely more productive than javascript and had no problems at all with debugging, documentation etc. But ultimately, this “walled garden”, as the OP puts it, drove our team away from Elm.
The major win of open source is that if something is missing, you can scratch your own itch (even if in a very hacky way). The Elm platform goes out of its way to block users from doing so. Surely they have their reasoning, and I understand their side, but it was a deal breaker for us anyway.
In any case, I wish all the luck to the Elm team, it just isn’t the best fit for us anymore. As an alternative, I can’t recommend Clojurescript + re-frame enough.
One of the points that stood out to me is the lack of up-to-date online tutorials and examples. This does make sense on some level given that the recent 0.19 release obsoleted a lot of old tutorials. I believe that the problem is amplified by how Elm discussion has moved to the slack walled garden: There’s been quite an increase in suggesting people should ask questions on the offical Elm slack instead of anywhere else, with a few obvious downsides.
As alternatives, there’s the public https://discourse.elm-lang.org/, but that doesn’t seem to be indexed particularly well by search engines. The /r/elm subreddit seems to have gone quiet, and stackoverflow typically has answers referring to older Elm versions.
However, I could see how hiding discussions in slack could in fact be a good thing for the same reasons: The existence of a lot of permanent content tied to old versions acts as a hinderance to putting out breaking changes, precisely because you end up in a documentation situation like Elm has now.
Perhaps a good compromise for a young project with frequent breaking changes would be to heavily encourage authors to clearly tag the content they put out with the language version?
But the reason we care about having a well-typed computer program to begin with is, in part, to detect corner cases and help the programmer figure out why an issue might be happening.
That doesn’t match my understanding of the term “corner case”. If all invariants for a given context can be expressed at the type level, then great. Usually where I see corner cases in my work is for types with so many inhabitants that it is not feasible to cover all cases. You wouldn’t write exhaustive logic for every inhabitant of an Integer type, for example. Types are great, but I don’t think it’s fair to say they commonly catch corner cases.
Yes, but I think we’re arguing around different interpretations of the term “corner case”.
I’m not exactly arguing against typed FP either; almost all of my work is done in Haskell and Elm.
I’m just arguing that saying “type inference helps catch corner cases” is either inaccurate, or is only applicable when the definition of “corner case” is so generous that the distinction stops being meaningful.
Type inference is really just about inferring the types of things based on the operations performed over values.
Yeah, I just thought probably the author’s formulation was a kind of informal way to say “type inference is a nice way to have a convenient static typing that prevents mistakes like null pointers and forgetting to handle every possible value.”
You wouldn’t write exhaustive logic for every inhabitant of an Integer type, for example.
Elm’s type system doesn’t work this way, but check out Agda, which does have a type system sophisticated enough that a programmer can actually write exhaustive logic (i.e. proofs) for every inhabitant of an Integer type.
My team was using Elm in production for about a year, but have been gradually replacing it with Typescript + React.
We started using it in version 0.18. We never bothered transitioning to 0.19 because there were a number of dependencies that weren’t being maintained, and we didn’t want to rewrite the functionality we were using from them.
The inability to install packages from anything but the official repo is a real pain. It made it really hard to reuse and modularize code. We had the choice of open sourcing anything we wanted to reuse, or adding extra steps to our build to copy files around.
There was also the problem of hiring and onboarding new team members. Like it or not, it’s far easier to hire someone to do front end work in Typescript than Elm. We developed some good tutorials for new team members to get started, but it still took more time to ramp up, since functional programming represents a big shift for a lot of people.
I really want Elm to succeed because it’s a joy to write, and the type system is incredibly helpful. But it will be a while before I recommend it to anyone for anything but fun projects.
Have you looked into Fable? Might have some of the benefits of Elm, but less restrictive and will interop beautifully with your TypeScript if you’re using Webpack.
I did not know about Fable. I’ll check it out. Thanks.
This seems a bit shortsighted.
This is very true. After using Elm and some other things in the last couple of years, I’ve made the commitment to try and never use anything that doesn’t have good built-in debugging, and sane errors.
They mention this really casually, but it’s a well-known problem (and affecting us too).
This is technically true. A work around is to fork a project and import it in your
elm.json
.This is almost uninteresting a comparison. Also there’s https://korban.net/elm/catalog/
The author didn’t mention ports at all, which was surprising. There is the Process package for sort of this, and you can also use service workers via ports.
Anyway. I agree with some of the post (I’ve used Elm professionally for almost 2 years), and I’ve wondered what else is out there that’s a better Elm? Purescript? ReasonML? Something Clojure or Lisp based? Any suggestions?
Of course there is a ClojureScript. If I need any JS over a few dozen lines, that’s where I go.
I hadn’t written any Clojure (or any Lisp, really) before, so I did the simple HackerRank “counting valleys” question in Clojure and it was really nice. Having used Elm for the last while had me already in a functional mindset, which helped a lot.
I’m curious to get some feedback on my ~28 lines of Clojure as well, so I’ll see if I can find a willing soul to critique it.
I can be happy to critique, if you like. I’ve not worked with many other Clojure programmers, but I’ve read a bunch of code and have written a bunch as well.
That’d be nice! It’s only 27 lines of code, and solving the simple HackerRank question I mentioned, so it might be hard without the full context (the question). But anyway, I’ve put the code in a gist: https://gist.github.com/jesse-c/bd7605b53cb4cb9390192475514bf9fb
I responded in full in the comments on the gist. Welcome to Clojure!
Thank you so much!
I have been exploring F#-to-JS with Fable, which has been surprisingly pleasant. For this project I also considered Elm and Purescript, but decided that Elm might be too foreign, and the company being a .NET shop made F# an easy choice over Purescript.
Fable looks interesting! Unfortunately I/we have never used .NET.
If you’re on Windows, that’s not a major issue. If you’re on a non-Windows platform, it might be slightly confusing to get started with – to the point of perhaps being worth it to look elsewhere.
i’m personally a fan of ocaml, but i would also use clojurescript with great pleasure if i had to join a project involving it.
I just replied to someone else who had suggested Clojurescript about my first time having just used Clojure. [1]
[1] https://lobste.rs/s/brvwey/elm_why_it_s_not_quite_ready_yet#c_rwwjoo
Re installing packages: have you seen elm-git-install? Not a mature tool etc. but at least there’s an option.
A note about the Elm package catalog (it’s my project): it’s far from complete. There are ~1700 packages available, but the catalog is currently at 390. It’s probably not a fair indication of the breadth of the ecosystem (yet).
We had tried either that or something similar last year but had to move away from it some reason (vague, I know). At the moment we’ve gotten rid of all our forks, but if we have the need again, I’ll suggest it. Thanks!
Why? Elm’s tagline on its landing page says, ‘A delightful language for reliable webapps.’.
Do you want to stay with the Elm architecture but move to a more powerful, older and battle-tested language? Then check out bucklescript-tea. Do you want the benefits of the language with a more type-safe take on ReactJS? Try ReasonReact.
That’s true! I suppose my reaction was more that React/Vue are purely frameworks, whereas Elm is a whole language with its own frameworks, etc.
Is probably of more interest for me. I have no idea about the ReasonML ecosystem, community, governance, etc. so I’ll have to check it out more.
Summary: author’s expectations of a young language exceed the actual implementation, so they write a Medium article.
If you can’t tell: slightly triggering article for me, and I don’t use/advocate for Elm. I’d much prefer if the author either pitched in and helped, or shrugged and moved on to something else. Somehow, yelling into the void about it is worse to me, I think because there are one or two good points in there sandwiched between non-constructive criticisms.
The article provides valuable information for people considering using Elm in production. The official line on whether Elm is production ready or not is not at all clear, and a lot of people suggest using it.
I didn’t like that he makes unrelated and unsupported claims in the conclusion (“Elm is not the fastest or safest option”). That’s not helpful.
I read “fastest” and “safest” as referring to “how fast can I can get work done” and “is this language a safe bet”, not fast and safe in the sense of performance. If that’s the right interpretation, then those conclusions flow naturally from the observations he makes in the article.
Right, the author made the same clarification to me on Twitter, so that’s definitely what he meant. In that sense, the conclusion is fine. Those are very ambiguous words though (I took them to mean “fastest runtime performance” and “least amount of runtime errors”).
Yeah definitely. I also was confused initially.
TBF, I was a little too snarky in my take. I don’t want to shutdown legitimate criticism.
That ambiguity is a problem. There’s also a chicken/egg problem with regard to marketing when discussing whether something is production ready. I’m not sure what the answer is.
It’s even more ambiguous for Elm. There are dozens of 100K+ line commercial code bases out there. How many should there be before the language is “production ready”? Clearly, for all those companies, it already is.
Perhaps the question is misguided and has reached “no true Scotsman” territory.
That’s one reason why this topic is touchy to me: things are never ready until the Medium-esque blogosphere spontaneously decides it is ready, and then, without a single ounce of discontinuity, everyone pretends like they’ve always loved Elm, and they’re excited to pitch in and put forth the blood, sweat, and tears necessary to make a healthy, growing ecosystem. Social coding, indeed.
In a sense, everyone wants to bet on a winner, be early, and still bet with the crowd. You can’t have all those things.
I like your last paragraph. When I think about it, I try to reach the same impossible balance when choosing technologies.
I even wrote a similar post about Cordova once (“is it good? is it bad?”). Hopefully it was a bit more considered as I’d used it for 4 years before posting.
The thing that bothers me with the developer crowd is somewhat different, I think. It’s the attempt to mix the other two unmixable things. On one hand, there’s the consumerist attitude to choosing technologies (“Does it work for me right now? Is it better, faster, cheaper than the other options?”). On the other hand, there are demands for all the benefits of open source like total transparency, merging your PR, and getting your favourite features implemented. Would anyone demand this of proprietary software vendors?
I’m not even on the core Elm team, I’m only involved in popularising Elm and expanding the ecosystem a bit, but even for me this attitude is starting to get a bit annoying. I imagine it’s worse for the core team.
Hey, thanks for your work on Elm. I’m much less involved than you, but even I find the “walled garden” complaints a little irritating. I mean, if you don’t like this walled garden, there are plenty of haphazard dumping grounds out there to play in, and even more barren desert. Nobody’s forcing anybody to use Elm! For what it’s worth, I think Evan and the Elm core team is doing great work. I’m looking forward to Elm 1.0, and I hope they take their time and really nail it.
The author of this article isn’t pretending to be an authority on readiness, and claiming that they’ll bandwagon is unwarranted. This article is from someone who was burned by Elm and is sharing their pain in the hopes that other people don’t get in over their heads.
Being tribal, vilifying the “Medium-esque blogosphere” for acts that the author didn’t even commit, and undermining their legitimate criticisms with “well, some people sure do love to complain!” is harmful.
I’d like to push back on this. What is “production ready”, exactly? Like I said in another comment, there are dozens of 100K+ line commercial Elm code bases out there. Clearly, for all those companies, it already is.
I’ve used a lot of other technologies in production which could easily be considered “not production ready”: CoffeeScript, Cordova, jQuery Mobile, Mapbox. The list goes on. They all had shortcomings, and sometimes I even had to make compromises in terms of requirements because I just couldn’t make particular things work.
The point is, it either works in your particular situation, or it doesn’t. The question is meaningless.
Here are my somewhat disjoint thoughts on the topic before the coffee has had a chance to kick in.
At a minimum, the language shouldn’t make major changes between releases that require libraries and codebases to be reworked. If it’s not at a point where it can guarantee such a thing, then it should state that fact up front. Instead, its creator and its community heavily promote it as being the best thing since sliced bread (“a delightful language for reliable webapps”) without any mention of the problems described in this post. New folks take this to be true and start investing time into the language, often quite a lot of time since the time span between releases is so large. By the time a new release comes out and changes major parts of the language, some of those people will have invested so much time and effort into the language that the notion of upgrading (100K+ line codebases, as you put it) becomes downright depressing. Not to mention that most of those large codebases will have dependencies that themselves will need upgrading or, in some cases, will be have to be deprecated (as
elm-community
has done for most of my libraries with the release of 0.19, for example).By promoting the language without mentioning how unstable it really is, I think you are all doing it a disservice. Something that should be perceived as good, like a new release that improves the language, ends up being perceived as a bad thing by a large number of the community and so they leave with a bad taste in their mouth – OP made a blog post about it, but I would bet the vast majority of people just leave silently. You rarely see this effect in communities surrounding other young programming languages and I would posit that it’s exactly because of how they market themselves compared to Elm.
Of course, in some cases it can’t be helped. Some folks are incentivized to keep promoting the language. For instance, you have written a book titled “Practical Elm” so you are incentivized to promote the language as such. The more new people who are interested in the language, the more potential buyers you have or the more famous you become. I believe your motivation for writing that book was pure and no one’s going to get rich off of a book on Elm. But, my point is that you are more bought into the language that others normally are.
That is the very definition of not-production-ready, isn’t it?
Disclaimer: I quit Elm around the release of 0.18 (or was it 0.17??) due to a distaste for Evan’s leadership style. I wrote a lot of Elm code (1 2 3 4 and others) and put some of it in production. The latter was a mistake and I regret having put that burden on my team at the time.
From what I’ve seen, many people reported good experiences with upgrading to Elm 0.19. Elm goes further than many languages by automating some of the upgrades with
elm-upgrade
.FWIW, I would also prefer more transparency about Elm development. I had to scramble to update my book when Elm 0.19 came out. However, not for a second I’m going to believe that I’m entitled to transparency, or that it was somehow promised to me.
To your other point about marketing, if people are making decisions about putting Elm into production based on its tagline, well… that’s just bizarre. For example, I remember looking at React Native in its early stages, and I don’t recall any extensive disclaimers about its capabilities or lack thereof. It was my responsibility to do that research - again, because limitations for one project are a complete non-issue for another project. There’s just no one-size-fits-all.
Finally, calling Elm “unstable” is simply baseless and just as unhelpful as the misleading marketing you allege. I get that you’re upset by how things turned out, but can’t we all have a discussion without exaggerated rhetoric?
Exactly my point: there is no such definition. All those technologies I mentioned were widely used at the time. I put them into production too, and it was a good choice despite the limitations.
And that’s great! The issue is the things that cannot be upgraded. Let’s take elm-combine (or parser-combinators as it was renamed to), for example. If you depended on the library in 0.18, then, barring the invention of AGI, there’s no automated tool that can help you upgrade because your code will have to be rewritten to use a different library because elm-combine cannot be ported to 0.19 (not strictly true, because it can be ported but only by the core team, but my point still stands because it won’t be). Language churn causes ecosystem churn which, in turn, causes pain for application developers so I don’t think it’s a surprise that folks get angry and leave the community when this happens given that they may not have had any prior warning before they invested their time and effort.
I don’t think it’s an exaggeration to call a language with breaking changes between releases unstable. To be completely honest, I can’t think of a better word to use in this case. Fluctuating? In flux? Under development? Subject to change? All of those fit and are basically synonymous to “unstable”. None of them are highlighted anywhere the language markets itself, nor by its proponents. I’m not making a judgement on the quality of the language when I say this. I’m making a judgement on how likely it is to be a good choice in a production environment, which brings me to…
They were not good choices, because, by your own admission, you were unable to meet your requirements by using them. Hence, they were not production-ready. Had you been able to meet your requirements and then been forced to make changes to keep up with them, then that would also mean they were not production-ready. From this we have a pretty good definition: production-readiness is inversely proportional to the likelihood that you will “have a bad time” after putting the thing into production. The more that likelihood approaches 0, the more production-ready a thing is. Being forced to spend time to keep up with changes to the language and its ecosystem is “having a bad time” in my book.
I understand that our line of work essentially entails us constantly fighting entropy and that, as things progress, it becomes harder and harder for them maintain backwards-compatibility but that doesn’t mean that nothing means anything anymore or that we can’t reason about the likelihood that something is going to bite us in the butt later on. From a business perspective, the more likely something is to change after you use it, the larger risk it poses. The more risks you take on, the more likely you are to fail.
I think your definition is totally unworkable. You’re claiming that technologies used in thousands upon thousands of projects were not production ready. Good luck with finding anything production ready then!
I’ve been working with Clojure for almost a decade now, and I’ve never had to rewrite a line of my code in production when upgrading to newer versions because Cognitect takes backwards compatibility seriously. I worked with Java for about a decade before that, and it’s exact same story. There are plenty of languages that provide a stable foundation that’s not going to keep changing from under you.
I am stating that being able to put something in production is different from said thing being production ready. You claim that there is no such thing as “production ready” because you can deploy anything which is a reduction to absurdity of the situation. Putting something into production and being successful with it does not necessarily make it production ready. It’s how repeatable that success is that does.
It doesn’t look like we’re going to get anywhere past this point so I’m going to leave it at that. Thank you for engaging and discussing this with me!
Thank you as well. As I said in another comment, this is the first time I tried having an extended discussion in the comments in here, and it hasn’t been very useful. Somehow we all end up talking past each other. It’s unfortunate. In a weird way, maybe it’s because we can’t interrupt each other mid-sentence and go “Hang on, but what about?…”. I don’t know.
This doesn’t respond to bogdan’s definition in good faith.
In response to your criticisms, bogdan proposed a scale of production-readiness. This means that there is no such distinction between “production-ready” and not “production-ready”. Elm is lower on this scale than most advocates imply, and the article in question provides supporting evidence for elm being fairly low on this scale.
What kind of discussion do you expect to have when the first thing you say to me is that I’m responding in bad faith? Way to go, my friend.
Frankly, I don’t really want to have a discussion with you. I’m calling you out because you were responding in bad faith. You didn’t address any of his actual points, and you dismissed his argument condescendingly. The one point you did address is one that wasn’t made, and wasn’t even consistent with bogdan’s stance.
In my experience, the crusader for truth and justice is one of the worst types of participants in a forum.
We may not have agreed, but bogdan departed from the discussion without histrionics, and we thanked each other.
But you still feel you have to defend his honour? Or are you trying to prove that I defiled the Truth? A little disproportionate, don’t you think?
(Also: don’t assign tone to three-sentence comments.)
I disagree that the question is meaningless just because it has a subjective aspect to it. A technology stack is a long term investment, and it’s important to have an idea how volatile it’s going to be. For example, changes like the removal the of the ability to do interop with Js even in your own projects clearly came as a surprise to a lot of users. To me a language being production ready means that it’s at the point where things have mostly settled down, and there won’t be frequent breaking changes going forward.
By this definition, Python wasn’t production ready long after the release of Python 3. What is “frequent” for breaking changes? For some people it’s 3 months, for others it’s 10 years. It’s not a practical criterion.
Even more interestingly, Elm has been a lot less volatile than most projects, so it’s production ready by your definition. Most people complain that it’s changing too slowly!
(Also, many people have a different perspective about the interop issue; it wasn’t a surprise. I don’t want to rehash all that though.)
Python 3 was indeed not production-ready by many people’s standards (including mine and the core team’s based on the changes made around 3.2 and 3.3) after its release up until about version 3.4.
“it’s improving too slowly” is not the same as “it’s changing too slowly”.
Sorry, this doesn’t make any sense.
By @Yogthos’s definition, neither Python 2 nor Python 3 were “production ready”. But if we’re going to write off a hugely popular language like that, we might as well write off the whole tech industry (granted, on many days that’s exactly how I feel).
Re Elm: again, by @Yogthos’s definition it’s perfectly production ready because it doesn’t make “frequent breaking changes”.
Python 2 and 3 became different languages at the split as evidenced by the fact that they were developed in parallel. Python 2 was production ready. Python 3 was not. The fact that we’re using numbers to qualify which language we’re talking about proves my point.
It took five years for Django to get ported to Python 3. (1 2)
You’re hanging on the wording here and “frequent” is not as important to Yogthos’ argument as “breaking changes” is.
I don’t think we’re going to get anywhere with this discussion by shifting goalposts.
I think most people agree that Python 3 was quite problematic. Your whole argument seems to be that just because other languages have problems, you should just accept random breaking changes as a fact of life. I strongly disagree with that.
The changes around ecosystem access are a HUGE breaking change. Basically any company that invested in Elm and was doing Js interop is now in a really bad position. They either have to stay on 0.18, re-implement everything they’re using in Elm, or move to a different stack.
Again, as I noted there is subjectivity involved here. My standards for what constitutes something being production ready are different than yours apparently. That’s fine, but the information the article provides is precisely what I’d want to know about when making a decision of whether I’d want to invest into a particular piece of technology or not.
I don’t think you are really aware of the changes to Elm because you’re seriously overstating how bad they were (“re- implement everything” was never the case).
I agree that there is useful information in the article – in fact, I try to read critical articles first and foremost when choosing technologies so it’s useful to have them. I never said that we should accept “random breaking changes” either (and it isn’t fair to apply that to Elm).
I still don’t see that you have a working definition of “production ready” – your definition seems to consist of a set with a single occupant (Clojure).
As an aside, this is the first time I’ve had an extended discussion in the comments here on Lobsters, and it hasn’t been very useful. These things somehow always end up looking like everyone’s defending their entrenched position. I don’t even have an entrenched position – and I suspect you may not either. Yet here we are.
Perhaps I misunderstand the situation here. If a company has an Elm project in production that uses Js interop, what is the upgrade path to 0.19. Would you not have to rewrite any libraries from the NPM ecosystem in Elm?
I worked with Java for around a decade before Clojure, and it’s always been rock solid. The biggest change that’s happened was the introduction of modules in Java 9. I think that’s a pretty good track record. Erlang is another great example of a stack that’s rock solid, and I can name plenty of others. Frankly, it really surprises me how cavalier some developer communities regarding breaking changes and regressions.
Forum discussions are always tricky because we tend to use the same words, but we assign different meanings to them in our heads. A lot of the discussion tends to be around figuring out what each person understands when they say something.
In this case it sounds like we have different expectations for what to expect from production ready technology. I’m used to working with technologies where regressions are rare, and this necessarily colors my expectations. My views on technology adoption are likely more conservative than majority of developers.
Prior to the 0.19 release, there was a way to directly call JS functions from Elm by relying on a purely internal mechanism. Naturally, some people started doing this, despite repeated warnings that they really shouldn’t. It wasn’t widespread, to my knowledge.
All the way in 2017, a full 17 months before 0.19 release, it was announced that this mechanism would be removed. It was announced again 5 months before the release.
Of course, a few people got upset and, instead of finding a migration path, complained everywhere they could. I think one guy wrote a whole UI framework based on the hack, so predictably he stomped out of the community.
There is an actual JS interop mechanism in Elm called ports. Anybody who used this in 0.18 (as they should have) could continue using it unchanged in 0.19. You can use ports to integrate the vast majority of JS libraries with Elm. There is no need to rewrite all JavaScript in Elm. However, ports are asynchronous and require marshalling data, which is why some people chose to use the internal shortcut (aka hack) instead.
So, if a company was using ports to interop with JS, there would be no change with 0.19. If it was using the hack, it would have to rewrite that portion of the code to use ports, or custom elements or whatever – but the rework would be limited to bindings, not whole JS libraries.
There were a few other breaking changes, like removing custom operators. However, Elm has a tool called elm-upgrade which helps to identify these and automatically update code where possible.
There were also fairly significant changes to the standard library, but I don’t think they were any more onerous than some of the Rails releases, for example.
Here are the full details, including links to previous warnings not to use this mechanism, if you’re interested: https://discourse.elm-lang.org/t/native-code-in-0-19/826
I hope this clarifies things for you.
Now, regarding your “rock solid” examples by which I think you mean no breaking changes. If it’s achievable, that’s good – I’m all for it. However, as a counterexample, I’ll bring up C++ which tied itself into knots by never breaking backward compatibility. It’s a mess.
I place less value on backward compatibility than you do. I generally think that backward compatibility ultimately brings software projects down. Therefore, de-prioritising it is a safer bet for ensuring the longevity of the technology.
Is it possible that there are technologies which start out on such a solid foundation that they don’t get bogged down? Perhaps – you bring up Clojure and Erlang. I think Elm’s core team is also trying to find that kind of foundation.
But whether Elm is still building up towards maturity or its core team simply has a different philosophy regarding backward compatibility, I think it’s at least very clear that that’s how it is if you spend any time researching it. So my view is that anybody who complains about it now has failed to do their research before putting it into production.
I feel like you’re glossing over the changes from native modules to using ports. For example, native modules allowed exposing external functions as Tasks allowing them to be composed. Creating Tasks also allows for making synchronous calls that return a Task Never a which is obviously useful.
On the other hand, ports can’t be composed like Tasks, and as you note can’t be used to call synchronous code which is quite the limitation in my opinion. If you’re working with a math library then having to convert the API to async pub/sub calls is just a mess even if it is technically possible to do.
To sum up, people weren’t just using native modules because they were just completely irresponsible and looking to shoot themselves in a foot as you seem to be implying. Being able to easily leverage existing ecosystem obviously saves development time, so it’s not exactly surprising that people started using native modules. Once you have a big project in production it’s not trivial to go and rewrite all your interop in 5 months because you have actual business requirements to work on. I’ve certainly never been in a situation where I could just stop all development and go refactor my code as long as I wanted.
This is precisely the kind of thing I mean when I talk about languages being production ready. How much time can I expect to be spending chasing changes in the language as opposed to solving business problems. The more breaking changes there are the bigger the cost to the business is.
I’m also really struggling to follow your argument regarding things like Rails or C++ to be honest. I don’t see these as justifying unreliable tools, but rather as examples of languages with high maintenance overhead. These are technologies that I would not personally work with.
I strongly disagree with the notion that backwards compatibility is something that is not desirable in tooling that’s meant to be used in production, and I’ve certainly never seen it bring any software projects down. I have however seen plenty of projects being brought down by brittle tooling and regressions.
I view such tools as being high risk because you end up spending time chasing changes in the tooling as opposed to solving business problems. I think that there needs to be a very strong justification for using these kinds of tools over ones that are stable.
I think we’re talking past each other again, so I’m going to wrap this up. Thank you for the discussion.
The question isn’t even close to meaningless… Classifying something as “production ready” means that it is either stable enough to rely on, or is easily swapped out in the event of breakage or deprecation. The article does a good enough job of covering aspects of elm that preclude it from satisfying those conditions, and it rightly warns people who may have been swept up by the hype around elm.
Elm has poor Interop, and is (intentionally) a distinct ecosystem from JS. This means that if Elm removes features you use, you’re screwed. So, for a technology like Elm (which is a replacement of JS rather than an enhancement) to be “production ready” it has to have a very high degree of stability, or at least long term support for deprecated features. Elm clearly doesn’t have this, which is fine, but early adopters should be warned of the risks and drawbacks in great detail.
Let’s keep it really simple, to me ‘production-ready’ is when the project version gets bumped to 1.0+. This is a pretty established norm in the software industry and usually a pretty good rule of thumb to judge by. In fact Elm packages enforce semantic versioning, so if you extrapolate that to Elm itself you inevitably come to the conclusion that hasn’t reached production-release readiness yet.
The term “production ready” is itself not at all clear. Some Elm projects are doing just fine in production and have been for years now. Some others flounder or fail. Like many things, it’s a good fit for some devs and some projects, and not for some others – sometimes for reasons that have little to do with the language or its ecosystem per se. In my (quite enjoyable!) experience with Elm, both official and unofficial marketing/docs/advocates have been pretty clear on that; but developers who can’t or won’t perceive nuance and make their own assessments for their own needs are likely to be frustrated, and not just with Elm.
I agree that there’s valuable information in this article. I just wish it was a bit less FUDdy and more had more technical detail.
[Comment removed by author]
I think there’s an angle to Elm’s marketing that justifies these kinds of responses: Those “author’s expectations” are very much encouraged by the way the Elm team presents their language.
Which criticisms do you find unfair, which are the good points?
I’m sympathetic to both Elm and the author here. I understand Elm’s marketing stance because they ask devs to give up freely mixing pure/impure code everywhere in their codebase on top of a new language and ecosystem. (In general, OSS’s perceived need for marketing is pretty out of hand at this point and a bit antithetical to what attracts me to it in the first place). OTOH it shouldn’t be possible to cause a runtime error in the way the author described, so that’s a problem. I’d have wanted to see more technical details on how that occurred, because it sounded like something that type safety should have protected him from.
Fair criticisms:
Unfair criticisms:
The conclusion gets a little too emotional for my taste.
Thanks for the detailed reply; the criticism of the article seems valid.
(As a minor point, the “PRs being open” criticism didn’t strike me as unsubstantiated because I’ve had enough similar experiences myself, but I can see how the article doesn’t argue that well. Certainly I’ve felt that it would be more honest/helpful for elm to not accept github issues/prs, or put a heavy disclaimer there that they’re unlikely to react promptly, and usually prefer to fix things their own way eventually.)
A lot of the things listed in the articles are things that have been explicitly done to make things harder for contributions to happen. The development of Elm has explicitly made choices to make things harder, and not in a merely incidental way.
This isn’t “the language is young” (well except for the debug point), a lot of this is “the language’s values go against things useful for people deploying to production”)
I don’t know, other than the point about the inability to write native modules and the longstanding open PR’s, all of the rest of the issues very much seem symptomatic of a young language.
The native module point sounds very concerning, but I don’t think I understand enough about elm or the ecosystem to know how concerning it is.
I’ve been vaguely following along with Elm, and the thng that makes me err on agreeing with this article is that the native module thing used to not be the case! It was removed! There was a semi-elegant way to handle interactions with existing code and it was removed.
There are “reasons”, but as someone who has a couple ugly hacks to keep a hybrid frontend + backend stack running nicely, I believe having those kinds of tricks are essential for bringing it into existing code bases. So seeing it get removed is a bit red flag for me.
Elm still has a lot of cool stuff, of course
I never relied on native modules, so I didn’t really miss them. But we now have ports, which I think is a much more principled (and interesting) solution. I felt that they worked pretty well for my own JS interop needs.
Stepping back a bit, if you require the ability do ugly hacks, Elm is probably not the right tool for the job. There are plenty of other options out there! I don’t expect Elm to be the best choice for every web front-end, but I do appreciate its thoughtful and coherent design. I’m happy to trade backward compatibility for that.
If you spend any amount of time in the Elm community you will find that contributions to the core projects are implicitly and explicitly discouraged in lots of different ways. Even criticisms of the core language and paradigms or core team decisions are heavily moderated on the official forums and subreddit.
Also how are we using the term “young”? In terms of calendar years and attention Elm is roughly on par with a language like Elixir. It’s probably younger in terms of developer time invested, but again this is a direct result of turning away eager contributors.
I think it’s fine for Elm to be a small project not intended for general production usage, but Evan and the core team have continually failed to communicate that intent.
I have not used elm, and have no opinion either way. But this strikes me as wrong:
There’s a quote I rather like: “UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things”.
Take something like monkey patching in Ruby or Python: I’ve definitely used it on 2 or 3 occasions where it helped me to fix a problem that would otherwise be hard to fix, for example to work around limitations in the stdlib.
But on the other hand, I’ve also seen people use it for no reason in particular, where it was clearly not needed.
Great power comes with great responsibility, and it’s been demonstrated many times that programmers will abuse power given to them. Giving users all the power is a perfectly valid choice, but does come with trade-offs, and this is also true for not giving power to users.
Phrasing it as “distrust of users” strikes me as an unconstructive way to have a conversation about this.
It’s really unfortunate when that happens, but it happens. I think I’ve seen it in almost all non-trivial open source projects.
If it’s really important for you, then friendly asking again after a few weeks (maybe on chat or mailiing list, rather than GitHub) often helps.
Of all the points mentioned in the article, the only one I consider a real issue is the fact that Elm is the most closed-source open source project I’m aware of.
I used Elm for ~2 years, really enjoyed it. Felt infinitely more productive than javascript and had no problems at all with debugging, documentation etc. But ultimately, this “walled garden”, as the OP puts it, drove our team away from Elm.
The major win of open source is that if something is missing, you can scratch your own itch (even if in a very hacky way). The Elm platform goes out of its way to block users from doing so. Surely they have their reasoning, and I understand their side, but it was a deal breaker for us anyway.
In any case, I wish all the luck to the Elm team, it just isn’t the best fit for us anymore. As an alternative, I can’t recommend Clojurescript + re-frame enough.
I know I’m old, because every time I see posts about Elm, I think it’s about an email client.
I was going to post the same thing. I used Elm for years, and much preferred it to Pine.
Ah Pine. It’s no elm.
One of the points that stood out to me is the lack of up-to-date online tutorials and examples. This does make sense on some level given that the recent 0.19 release obsoleted a lot of old tutorials. I believe that the problem is amplified by how Elm discussion has moved to the slack walled garden: There’s been quite an increase in suggesting people should ask questions on the offical Elm slack instead of anywhere else, with a few obvious downsides.
As alternatives, there’s the public https://discourse.elm-lang.org/, but that doesn’t seem to be indexed particularly well by search engines. The /r/elm subreddit seems to have gone quiet, and stackoverflow typically has answers referring to older Elm versions.
However, I could see how hiding discussions in slack could in fact be a good thing for the same reasons: The existence of a lot of permanent content tied to old versions acts as a hinderance to putting out breaking changes, precisely because you end up in a documentation situation like Elm has now.
Perhaps a good compromise for a young project with frequent breaking changes would be to heavily encourage authors to clearly tag the content they put out with the language version?
I hope Mint will gain traction, it looks like great alternative for Elm. It is much simpler and allows easy js interop.
No it doesn’t. It uses type inference to, you know, infer types.
But the reason we care about having a well-typed computer program to begin with is, in part, to detect corner cases and help the programmer figure out why an issue might be happening.
That doesn’t match my understanding of the term “corner case”. If all invariants for a given context can be expressed at the type level, then great. Usually where I see corner cases in my work is for types with so many inhabitants that it is not feasible to cover all cases. You wouldn’t write exhaustive logic for every inhabitant of an
Integer
type, for example. Types are great, but I don’t think it’s fair to say they commonly catch corner cases.Null is a pretty common kind of “corner case.” Being able to use
Maybe Integer
helps with that!Yes, but I think we’re arguing around different interpretations of the term “corner case”.
I’m not exactly arguing against typed FP either; almost all of my work is done in Haskell and Elm.
I’m just arguing that saying “type inference helps catch corner cases” is either inaccurate, or is only applicable when the definition of “corner case” is so generous that the distinction stops being meaningful.
Type inference is really just about inferring the types of things based on the operations performed over values.
Yeah, I just thought probably the author’s formulation was a kind of informal way to say “type inference is a nice way to have a convenient static typing that prevents mistakes like null pointers and forgetting to handle every possible value.”
Elm’s type system doesn’t work this way, but check out Agda, which does have a type system sophisticated enough that a programmer can actually write exhaustive logic (i.e. proofs) for every inhabitant of an Integer type.
I am aware of Agda, Idris, etc. I’m quite certain the author of the Medium post is not talking about this.