Scala isn't fun anymore(alexn.org)
alexn.org
Scala isn't fun anymore
https://alexn.org/blog/2022/09/09/scala-isnt-fun-anymore/
390 comments
Am I the only one that doesn't think this is really all that bad? I'll admit that I've not ever written a line of Scala, but in principal it seems like the only people who have to follow this license will be those who can afford it.
Sure, true FOSS is always better, bit the maintainers have to eat somehow. If you're making 25m+ ARR and are using their software, maybe you should be paying them something.
Sure, true FOSS is always better, bit the maintainers have to eat somehow. If you're making 25m+ ARR and are using their software, maybe you should be paying them something.
The problem is that there's nothing stopping them from removing that 25m limit and jacking up the price tomorrow. It's putting your company at the mercy of another company which is not an ideal position.
It's also sort of a meta problem. You generally want to use well known libraries/frameworks so that you can hire people with experience. If other companies stop using it because of the above you probably want to stop as well even if you are not worried about hte license.
It's also sort of a meta problem. You generally want to use well known libraries/frameworks so that you can hire people with experience. If other companies stop using it because of the above you probably want to stop as well even if you are not worried about hte license.
I think it presents a problem beyond paying.
At my job, I can't just reach for Akka. I need to talk to someone who has the authority to purchase a $2,000/year/core license. If I'm deploying something to 6 instances with 4 cores each, that's $48,000/year for a pretty small deployable. It might be totally worth the price, but I'm definitely going to need to justify to someone that we're going to spend a fifth the price of an engineer because I want to use Akka for this small thing. People will propose alternatives. Before, if Akka was an average addition to the project, it was fine. Most things are average. Now, it's an average addition when we should have used something else and it's costing is $48,000/year.
What happens when we want to scale it up to 24 instances for a week to handle unexpected load? Do we pay $192,000? I'm not trying to sound difficult. I just know the types of questions that will come up in meetings. Likewise, how are we going to account for our Akka usage? Do engineers put it in a spreadsheet that they all forget exist? Won't they just forget when they add a new deployable or when they scale something up? How do we alert accounting or whomever that they need to pay additional license fees when we deploy something new or scale up?
I don't need the same meetings around FOSS. I don't need to involve accounting with FOSS. I don't need to figure out how we're going to sort out the billing. Yes, all these instances will have charges from AWS or whatever, but those are already handled. Yes, companies sometimes buy licenses from JetBrains for their IDEs, but you don't have to worry about those license fees once the code is written - it's a production cost, not a running cost. Yes, after several years Akka goes back to open source (so it isn't a liability forever), but if you keep updating it (including security updates) then it keeps being that liability you need to pay for.
Then there's the issue of ecosystem and vitality. The $2,000/core price is going to shrink the ecosystem down to a tiny fraction of what it used to be. I can hear the comments in the meeting now: why would we be paying $2,000/year/core to buy into a dying ecosystem?
I think the per-core license scheme makes sense to the maintainers - the more you use it, the more value and revenue you're generating with it, the more you should pay us. However, this creates two problems: 1) it makes it hard to deploy low-margin services using Akka so you can only use it in high-margin situations; 2) it means that you really don't know what it's going to cost if you scale up - how many cores are you going to be using a year or two from now?
Microsoft licenses Visual Studio to companies earning over $1M/year, but they're licensing it on a per-engineer basis rather than per-core. Telling a company, "that engineer you're paying $100,000-500,000/year is going to cost you an additional $500-1,000/year," is a very understandable cost and seems like a small/marginal cost per engineer. Telling a company, "that engineer that chose to use Akka is going to cost you an additional $2,000-3,000,000/year," isn't the same thing at all. 100 instances with 16 cores each is $3.2M. You can argue that the company is using Akka so much so they should be paying that much, but at the same time it means that maybe the company would have been better hiring a different engineer that would have used anything other than Akka. If the company had gone with Go or C#, they wouldn't be spending that $3.2M. The company would be better off if they hired a different engineer who wrote the system in Go rather than someone who decided they liked Scala and Akka.
Yes, I'd say it is that bad. The ecosystem will shrivel as people turn away from Akka, it will be difficult to get it approved as you'll need to go through meetings and come up with ways of accounting and paying for it, and the pricing scheme makes it very difficult to offer lower margin services and presents the company with potentially nebulous costs depending on how successful it is.
It's not just about paying. There's so much crap that can happen when you build your stuff around something proprietary. I'm not saying Lightbend will be like Oracle, but companies literally spend lots of money building proofs-of-concept using other databases to get negotiating leverage with Oracle - "see, we ported part of our thing to Postgres so unless you give us a good deal, we'll just replace you." At what point would my company start doing that with Lightbend and wasting my time as an engineer on nonsense? Does Lightbend end up having a "we caught a whale" mentality if my thing takes off or would they say, "oh, we're happy you're successful and we'll cap your license fees at $25,000/year - you clearly shouldn't have to spend millions a year paying us"? Lots of people have talked on here about building your product on someone else's platform. Usually that's about building on Facebook or Twitter who might cut off your access. Often enough, we talk about proprietary databases and lock-in worries. Building on a proprietary library like Akka isn't that different. You're going to be beholden to Lightbend.
I do think that we are too averse to paying for things, but I also genuinely fear the land-and-expand strategy that so many companies have. Maybe it's just $10,000/year today, but that could easily skyrocket under certain circumstances - and it's not always easy to migrate off something once you're on it.
At my job, I can't just reach for Akka. I need to talk to someone who has the authority to purchase a $2,000/year/core license. If I'm deploying something to 6 instances with 4 cores each, that's $48,000/year for a pretty small deployable. It might be totally worth the price, but I'm definitely going to need to justify to someone that we're going to spend a fifth the price of an engineer because I want to use Akka for this small thing. People will propose alternatives. Before, if Akka was an average addition to the project, it was fine. Most things are average. Now, it's an average addition when we should have used something else and it's costing is $48,000/year.
What happens when we want to scale it up to 24 instances for a week to handle unexpected load? Do we pay $192,000? I'm not trying to sound difficult. I just know the types of questions that will come up in meetings. Likewise, how are we going to account for our Akka usage? Do engineers put it in a spreadsheet that they all forget exist? Won't they just forget when they add a new deployable or when they scale something up? How do we alert accounting or whomever that they need to pay additional license fees when we deploy something new or scale up?
I don't need the same meetings around FOSS. I don't need to involve accounting with FOSS. I don't need to figure out how we're going to sort out the billing. Yes, all these instances will have charges from AWS or whatever, but those are already handled. Yes, companies sometimes buy licenses from JetBrains for their IDEs, but you don't have to worry about those license fees once the code is written - it's a production cost, not a running cost. Yes, after several years Akka goes back to open source (so it isn't a liability forever), but if you keep updating it (including security updates) then it keeps being that liability you need to pay for.
Then there's the issue of ecosystem and vitality. The $2,000/core price is going to shrink the ecosystem down to a tiny fraction of what it used to be. I can hear the comments in the meeting now: why would we be paying $2,000/year/core to buy into a dying ecosystem?
I think the per-core license scheme makes sense to the maintainers - the more you use it, the more value and revenue you're generating with it, the more you should pay us. However, this creates two problems: 1) it makes it hard to deploy low-margin services using Akka so you can only use it in high-margin situations; 2) it means that you really don't know what it's going to cost if you scale up - how many cores are you going to be using a year or two from now?
Microsoft licenses Visual Studio to companies earning over $1M/year, but they're licensing it on a per-engineer basis rather than per-core. Telling a company, "that engineer you're paying $100,000-500,000/year is going to cost you an additional $500-1,000/year," is a very understandable cost and seems like a small/marginal cost per engineer. Telling a company, "that engineer that chose to use Akka is going to cost you an additional $2,000-3,000,000/year," isn't the same thing at all. 100 instances with 16 cores each is $3.2M. You can argue that the company is using Akka so much so they should be paying that much, but at the same time it means that maybe the company would have been better hiring a different engineer that would have used anything other than Akka. If the company had gone with Go or C#, they wouldn't be spending that $3.2M. The company would be better off if they hired a different engineer who wrote the system in Go rather than someone who decided they liked Scala and Akka.
Yes, I'd say it is that bad. The ecosystem will shrivel as people turn away from Akka, it will be difficult to get it approved as you'll need to go through meetings and come up with ways of accounting and paying for it, and the pricing scheme makes it very difficult to offer lower margin services and presents the company with potentially nebulous costs depending on how successful it is.
It's not just about paying. There's so much crap that can happen when you build your stuff around something proprietary. I'm not saying Lightbend will be like Oracle, but companies literally spend lots of money building proofs-of-concept using other databases to get negotiating leverage with Oracle - "see, we ported part of our thing to Postgres so unless you give us a good deal, we'll just replace you." At what point would my company start doing that with Lightbend and wasting my time as an engineer on nonsense? Does Lightbend end up having a "we caught a whale" mentality if my thing takes off or would they say, "oh, we're happy you're successful and we'll cap your license fees at $25,000/year - you clearly shouldn't have to spend millions a year paying us"? Lots of people have talked on here about building your product on someone else's platform. Usually that's about building on Facebook or Twitter who might cut off your access. Often enough, we talk about proprietary databases and lock-in worries. Building on a proprietary library like Akka isn't that different. You're going to be beholden to Lightbend.
I do think that we are too averse to paying for things, but I also genuinely fear the land-and-expand strategy that so many companies have. Maybe it's just $10,000/year today, but that could easily skyrocket under certain circumstances - and it's not always easy to migrate off something once you're on it.
> You can argue that the company is using Akka so much so they should be paying that much, but at the same time it means that maybe the company would have been better hiring a different engineer that would have used anything other than Akka. If the company had gone with Go or C#, they wouldn't be spending that $3.2M. The company would be better off if they hired a different engineer who wrote the system in Go rather than someone who decided they liked Scala and Akka.
Or even fork it, continue development and just hire few more engineers. There is no amount of consulting that you can provide for a library that would be worth the money
Or even fork it, continue development and just hire few more engineers. There is no amount of consulting that you can provide for a library that would be worth the money
or akka on java.
Thanks for explaining that, makes more sense what the fuss is all about.
i am rewritting all of our projects (about 20 or so) to get off akka as we speak. Pain in the arse, but has to be done. It's a shame. Was fun while it lasted.
Could you add a link (or explanation in parentheses) that BSL means Business Source License and not Boost Software License? I was confused for a few about why people would be up in arms about the boost license which seems to me like an MIT variant.
2.6.19 will be forked and a community-driven Akka will emerge eventually.
Has a champion risen to the task yet?
Forking a project is no easy feat. Certainly not one the size of Akka. You need a corporate backer who is going to put at least one person full time on it. I've seen plenty of forks start out with the best of intentions only to slowly fade in to nothing.
Forking a project is no easy feat. Certainly not one the size of Akka. You need a corporate backer who is going to put at least one person full time on it. I've seen plenty of forks start out with the best of intentions only to slowly fade in to nothing.
https://www.theregister.com/2022/09/08/open_source_biz_sick_...
Here's an article on it. Their logic actually makes sense. Not that I support gouging customers, but when you consider how there are massive billion dollar companies with expensive lawyers figuring out how to end-around OSS (via SaaS, etc) this is the logical conclusion. A lot of companies make a lot of money on OSS and give little to nothing in return. This isn't in the spirit of OSS but company men don't really care. So it seems like Akka finally got sick of it and is now coming to collect its (without question) overdue paycheck from these people. It's just unfortunate they went so aggressive with it. $2000/vCPU/year will do a lot of damage to smaller projects in the process of sinking the billion dollar open source leeches in the process.
Here's an article on it. Their logic actually makes sense. Not that I support gouging customers, but when you consider how there are massive billion dollar companies with expensive lawyers figuring out how to end-around OSS (via SaaS, etc) this is the logical conclusion. A lot of companies make a lot of money on OSS and give little to nothing in return. This isn't in the spirit of OSS but company men don't really care. So it seems like Akka finally got sick of it and is now coming to collect its (without question) overdue paycheck from these people. It's just unfortunate they went so aggressive with it. $2000/vCPU/year will do a lot of damage to smaller projects in the process of sinking the billion dollar open source leeches in the process.
If you’re making $25mil in revenue why is it out of the question to pay for licenses?
Why would you? License requisition is a real pain, they have to be factored into the budget, depreciated, etc. If you can instead simply pull in OSS and hide it behind a SaaS implementation (thereby complying with licenses) you can leverage it to make money. I don't think Stallman saw this coming.
Some companies do better than others. For example, FAANG level companies typically have teams that do give back. In some cases several orders of magnitude more than they take from popular projects. It's the in-betweens, the other companies that don't do anything other than leech.
Some companies do better than others. For example, FAANG level companies typically have teams that do give back. In some cases several orders of magnitude more than they take from popular projects. It's the in-betweens, the other companies that don't do anything other than leech.
> pull in OSS and hide it behind a SaaS implementation (thereby complying with licenses)
sorry, but you can do that shit anymore:
https://wikipedia.org/wiki/Open_Software_License#Network_dep...
sorry, but you can do that shit anymore:
https://wikipedia.org/wiki/Open_Software_License#Network_dep...
My interpretation of that clause is it applies to distributing code over a network. The most common example of this is serving javascript to a web browser. I'm pretty sure putting an API in front of a server that happens to run open source software doesn't count as "distribution", which is what we're talking about here with SAAS providers and Akka. If it does, then every site that is backed by servers running linux and not distributing their GPL license to clients is also in violation.
I would disagree with your assessment. OSL was specifically crafted, to close this exact loophole:
> Most other open source licenses treat such network uses of software as internal to the company that runs the server, and they don't require disclosure of source code. That is seen by many nowadays as a loophole that permits large online companies to avoid their reciprocal source code obligations.
http://rosenlaw.com/OSL3.0-explained.htm#_Toc187293088
> Most other open source licenses treat such network uses of software as internal to the company that runs the server, and they don't require disclosure of source code. That is seen by many nowadays as a loophole that permits large online companies to avoid their reciprocal source code obligations.
http://rosenlaw.com/OSL3.0-explained.htm#_Toc187293088
Sorry, I didn't read your link carefully enough. I stand corrected, that does indeed seem to be the only reasonable interpretation. That said, this clause only exists in this particular OSL license, so it only applies to software distributed under it. Some quick googling indicates that OSL is 20 years old, and OSL v3 (the latest version), is 17. Despite that, it doesn't appear to have any significant usage. PyPi, for example, lists 10 software packages distributed under it [1], out of 387,658 total. So it certainly doesn't seem like a practical solution to the problem.
I suspect the reason that nobody uses it is due to its toxicity - it taints anything that transitively uses it in any practical way. This leads to all sorts of nonsensical violations. For example, say you write a document in a word processor that uses a leftpad lib distributed under this license. Then you email that document to someone else. Congratulations, you're now in violation of the license - you distributed a "derivative work" of the leftpad lib to someone "other than you" over a "network".
The terms of this license are so restrictive and cumbersome as to make it basically useless. Anything you publish under it can't effectively be used by the vast majority of the people who would want to use it, at which point you might as well not publish your work at all. I certainly wouldn't view this as a panacea for solving the SaaS-wrapping-OS-code problem.
[1] https://pypi.org/search/?c=License+%3A%3A+OSI+Approved+%3A%3...
I suspect the reason that nobody uses it is due to its toxicity - it taints anything that transitively uses it in any practical way. This leads to all sorts of nonsensical violations. For example, say you write a document in a word processor that uses a leftpad lib distributed under this license. Then you email that document to someone else. Congratulations, you're now in violation of the license - you distributed a "derivative work" of the leftpad lib to someone "other than you" over a "network".
The terms of this license are so restrictive and cumbersome as to make it basically useless. Anything you publish under it can't effectively be used by the vast majority of the people who would want to use it, at which point you might as well not publish your work at all. I certainly wouldn't view this as a panacea for solving the SaaS-wrapping-OS-code problem.
[1] https://pypi.org/search/?c=License+%3A%3A+OSI+Approved+%3A%3...
> That said, this clause only exists in this particular OSL license, so it only applies to software distributed under it.
Nope:
https://choosealicense.com/licenses/agpl-3.0
https://choosealicense.com/licenses/cecill-2.1
https://choosealicense.com/licenses/eupl-1.2
> Some quick googling indicates that OSL is 20 years old, and OSL v3 (the latest version), is 17
what does that have to do with anything? A license can be old, its still valid.
> The terms of this license are so restrictive and cumbersome as to make it basically useless
I see this often. This is business speak for "we don't like the terms of some license, so that license is useless for everyone". For anyone willing to respect the license terms, they can have full access to the software.
Nope:
https://choosealicense.com/licenses/agpl-3.0
https://choosealicense.com/licenses/cecill-2.1
https://choosealicense.com/licenses/eupl-1.2
> Some quick googling indicates that OSL is 20 years old, and OSL v3 (the latest version), is 17
what does that have to do with anything? A license can be old, its still valid.
> The terms of this license are so restrictive and cumbersome as to make it basically useless
I see this often. This is business speak for "we don't like the terms of some license, so that license is useless for everyone". For anyone willing to respect the license terms, they can have full access to the software.
> If you’re making $25mil in revenue why is it out of the question to pay for licenses?
Turn it around: the kind of company that makes $25mil in revenue does so in part by figuring out what expenses it can negate or avoid. If they don't have to pay for licenses, they won't.
Completely hypothetical anecdote certainly not based on personal experience working in the Bay: an Ops director who saved 50% on MSFT server license costs by only paying for the servers in the DC acting as current primary. "They are not taking production traffic so they are not in use, ergo no need to pay."
As an engineer this logic may disgust you but it's the kind of thing that gets you promoted and 'in good' with "the business."
PS. It's a similar principal to your filthy rich relatives who are surly misers and share nothing with everyone. (And they have no sense of humor, too!)
Turn it around: the kind of company that makes $25mil in revenue does so in part by figuring out what expenses it can negate or avoid. If they don't have to pay for licenses, they won't.
Completely hypothetical anecdote certainly not based on personal experience working in the Bay: an Ops director who saved 50% on MSFT server license costs by only paying for the servers in the DC acting as current primary. "They are not taking production traffic so they are not in use, ergo no need to pay."
As an engineer this logic may disgust you but it's the kind of thing that gets you promoted and 'in good' with "the business."
PS. It's a similar principal to your filthy rich relatives who are surly misers and share nothing with everyone. (And they have no sense of humor, too!)
> the kind of company that makes $25mil in revenue does so in part by figuring out what expenses it can negate or avoid.
Cutting expenses has no direct impact on revenue.
For many companies, it is better to have small recurring expenses than to take on certain types of risk.
Cutting expenses has no direct impact on revenue.
For many companies, it is better to have small recurring expenses than to take on certain types of risk.
The cost for the license would be more than the cost for the hardware to run it tho. We're talking literally doubling, maybe more, of the costs.
Coz you want to make $25 mil in revenue instead of $20 mil in revenue.
The cost is so high actually forking and developing the fork is probably cheaper. Especially for a big company.
Imagine app costing you 100k in hardware, 1 mil yearly in engineering cost but 5 mil in licensing cost just because you have big nice cluster with a bunch of modern high core count CPUs
The cost is so high actually forking and developing the fork is probably cheaper. Especially for a big company.
Imagine app costing you 100k in hardware, 1 mil yearly in engineering cost but 5 mil in licensing cost just because you have big nice cluster with a bunch of modern high core count CPUs
Because $25mil in revenue might still mean less profit than the cost of Akka licenses will add.
Remember, Revenue is before applying costs - costs like extra million here or there from licensing and costs of servicing the license which I think many people forget about. Especially when the software doesn't have some automated methods of license management.
Remember, Revenue is before applying costs - costs like extra million here or there from licensing and costs of servicing the license which I think many people forget about. Especially when the software doesn't have some automated methods of license management.
It's only been a week since the announcement, I'd expect it'll take a while.
Given that thousands of projects are dependent on it, I would hope so.
https://mvnrepository.com/artifact/com.typesafe.akka/akka-ac...
https://mvnrepository.com/artifact/com.typesafe.akka/akka-ac...
Surely it's the death of Akka inside large enterprises (outside of very niche, already written, applications). How can they justify the enormous departmental cost? If a small team in a large company is creating a new product why on earth would they choose to use Akka?
If you're a small company, likely to never hit $25m ARR, this won't affect you... Or is a ticking time bomb should you ever cross that threshold.
If you're a small company, likely to never hit $25m ARR, this won't affect you... Or is a ticking time bomb should you ever cross that threshold.
Imo this kind of license is a huge PITA with containerized workloads that autoscale, etc. Would one pay based on average core usage or peak usage?
As much as people like to rant about license managers used in proprietary software (and hardware from IBM...), that's a necessary feature for handling that kind of license well.
They kind of went down the communist route, but backwards? From public property to "tax the rich"
I don't have a ton to say here, the article says it all really. But this also reflects my experience when developing with Scala and although I love the language and its brevity, I went back to Java because I hated the Scala toolchain, sbt, dependency issues, etc. Basically, I like the language in isolation but the overall experience was horrible.
Java has the same dependency issues? I vividly remember spending days on jars shading in Maven. Basically, a single approach that would solve this, irrespective of the language, would be isolating dependency trees of every library from each other, essentially duplicating the code of many common libraries in RAM (like Docker, but for libraries inside the same process). There's an option to do that in Maven, but it's not the default. And it still would not work for dependencies where there should be only a single instance of it in RAM, like for example loggers...
I only very rarely see this in Java, even in huge monoliths. Not that there's a technical reason for this; I think there's a cultural expectation that you don't break backwards compatibility with Java libraries. Perhaps the Scala world is more cutting-edge and fluid so there are different cultural expectations.
The OP mentions Jackson. Jackson 1.x -> 2.x changed the package (so they are wholly separate libraries), Jackson 2.x -> 3.x will do it again. I've never had backwards compatibility issues with Jackson. I don't know what someone could be doing in jackson-module-scala that breaks with a minor version bump.
The OP mentions Jackson. Jackson 1.x -> 2.x changed the package (so they are wholly separate libraries), Jackson 2.x -> 3.x will do it again. I've never had backwards compatibility issues with Jackson. I don't know what someone could be doing in jackson-module-scala that breaks with a minor version bump.
Jackson doesn't have a stable API for building modules. You have to get elbow deep in their internals, which is already scary enough given that it's an old and highly performant library, but the bad part is that there's no formal commitment to maintaining compatibility. You just have to hope that the modules you use are popular enough that they will test them and make an effort not to break them. I've had an application break on a patch version bump of Jackson.
I have personally spent so much time fussing with runtime ClassDefNotFound and MethodNotFound errors in Java that I am no longer able to respond to assertions that Java is type-safe with anything but an incoherent stream of cursing and rage tears.
But Scala somehow seems to take all of that and intensify it. I have heard that Scala 3 is supposed to improve this, but I don't anticipate being able to adopt Scala 3 before the heat death of the universe.
But Scala somehow seems to take all of that and intensify it. I have heard that Scala 3 is supposed to improve this, but I don't anticipate being able to adopt Scala 3 before the heat death of the universe.
Those sorts of java runtime errors largely depend on programmers' insistence on doing things via reflection, and it will be the same in any programming language: Like most drugs, at first reflection seems you've opened a new door into enlightenment, until eventually you find yourself sleeping in a gutter with half your teeth missing and wondering why it didn't work out as expected. A lot of Java open source is addicted to this stuff.
Scala just adds more drugs to the cocktail.
Scala just adds more drugs to the cocktail.
I don't think that this is entirely fair to Java programmers. Java's designers decided early on to lean fairly hard on reflection. Not just by giving Java strong reflective capabilities, but by sometimes deliberately choosing not to give Java great facilities for solving problems without using reflection.
When I first came to Java from .NET, I was initially shocked at how heavily it was used in the Java space. (.NET arguably has even more powerful reflection facilities than Java does, but they are typically avoided at all costs.) But it didn't take me very long to realize that many of the C# language features I would have chosen to use instead of reflection simply don't have equivalents in Java. So, I don't think that it's necessarily that Java developers are addicted to this stuff, so much as that they just haven't been given any other choice.
When I first came to Java from .NET, I was initially shocked at how heavily it was used in the Java space. (.NET arguably has even more powerful reflection facilities than Java does, but they are typically avoided at all costs.) But it didn't take me very long to realize that many of the C# language features I would have chosen to use instead of reflection simply don't have equivalents in Java. So, I don't think that it's necessarily that Java developers are addicted to this stuff, so much as that they just haven't been given any other choice.
Java's type system supports code gen. See projects like the Checker framework or NullAway
The errors are created by failures on finding dependencies.
Not sure what you're doing with Java but that's not a common problem at all. Are you just aggressively stripping code and dealing with the fallout?
Working on projects that involve big frameworks with deep and ever-shifting dependency trees. So upgrading an existing dependency or taking a new one could often be a risky move.
Ground zero for most of them was Guava, which I unfortunately could not avoid due to it being a transitive dependency. And, even more unfortunately, Guava types were being exposed on the direct dependency's public API, so package relocation was not an easy option.
Ground zero for most of them was Guava, which I unfortunately could not avoid due to it being a transitive dependency. And, even more unfortunately, Guava types were being exposed on the direct dependency's public API, so package relocation was not an easy option.
Guava is an outlier. While they do honor semver, they’re already on version 31.1, meaning they have felt they needed to break backward compatibility dozens of times, and it’s likely your dependencies require conflicting versions just by accident of when they were written. I guess it’s because the maintainers live in a monorepo and just force any changes they need?
The other interesting corollary to this is: if your package relies on one like Guava, and it is not bumping its major version number every time it updates the version of Guava it depends on, then your package does not itself honor semver.
Much like libraries that run on Scala 2.11 or 2.12, I can imagine a system where I maintain several compatible minor versions (or named forks) of a library, each patched to use a different major version of Guava, and letting a caller solve for exactly which version of everything is compatible with everything else. But the more API churn we face, the harder this is.
Incompatible versions of transitive dependencies, incompatible libs that your web server added, this is the default in Java unless you pay close attention to your dependencies.
That wasn't my experience with Java back in the day.
What the article describes with Scala rings true, and I stopped using it (due to a job change) more than 2 years ago! So Scala was already going down this route 2 years ago.
What the article describes with Scala rings true, and I stopped using it (due to a job change) more than 2 years ago! So Scala was already going down this route 2 years ago.
> That wasn't my experience with Java back in the day
It is still not a typical experience. In our team, we try _very_ hard to avoid reflection and these errors are very very rare (never in Production).
It is still not a typical experience. In our team, we try _very_ hard to avoid reflection and these errors are very very rare (never in Production).
JBang [1] can help a lot here, especially with the new "BOM POM" feature. The experience feels closer to Go than Maven.
[1] - https://www.jbang.dev/documentation/guide/latest/dependencie...
[1] - https://www.jbang.dev/documentation/guide/latest/dependencie...
Jep, this is really an issue of how the JVM and Classloaders are architected. Rust essentially chooses the other side of the sea, which is better in some sense, but worse in others (which we will see once the ecosystem grows).
A configurable middleground is needed, but it's not an easy task to get that done.
A configurable middleground is needed, but it's not an easy task to get that done.
Java has the same dependency issues. But, from the article, it seems like there might be something cultural within the Scala community that contributes to the problem. Most Java libraries, in my experience, are relatively flat. The article gives an example of HikariCP, which depends on a random JDBC library from Akka. Obviously, that situation is going to end terribly given the popularity of Akka. As soon as Akka updates their library version, HikariCP has to as well or the two dependencies will get hopelessly out of sync. I don't know what `akka-persistence-jdbc ` does, but it can't be so important that it justifies the crazy dependency structure.
HikariCP is a Java library I thought, at least I’ve used it in many Java projects, so I’m not sure what that has to do with Scala.
Scala doesn't care about backwards compatibility. They break stuff all the time, And so major libraries are tenuously hanging on to whatever version they were targeted at. Akka prints out messages if it finds jars with even different minor versions.
Dependency management is painful almost everywhere. I see a glimmer of hope for the future in Unison, a language in which code exists as content-addressed ASTs. Dependency version conflicts cannot exist; there is not even a need to resolve a set of dependency versions.
https://www.unison-lang.org/learn/the-big-idea/
https://www.unison-lang.org/learn/the-big-idea/
> Basically, a single approach that would solve this, irrespective of the language, would be isolating dependency trees of every library from each other
Doesn't solve the problem completely because it is normal that applications need libraries to interoperate; consider case where application is passing objects between two libraries that both use types from a third library.
Doesn't solve the problem completely because it is normal that applications need libraries to interoperate; consider case where application is passing objects between two libraries that both use types from a third library.
A major problem is that Maven (and friends) doesn’t distinguish between API dependencies (the API of a library using types from the API of another library) and implementation dependencies (a library depending on another library as an implementation detail). If that distinction were made consistently, implementation dependencies could indeed be separated into a dedicated classloader for each library, and you’d only have to worry about API dependencies, which would go a long way.
The Java 9 Modules architecture would have been an opportunity to introduce something like that, but alas they didn’t.
The Java 9 Modules architecture would have been an opportunity to introduce something like that, but alas they didn’t.
I believe that separating interface from implementation doesn't really solve the problem, it just shrinks it. E.g. what if you depend on two libraries that re-export classes from different versions of a third library?
I think that if you truly want to solve the problem, you need to extend the definition of the fully qualified classname to include the notion of a breaking version reference. Kind of like what folks now sometimes do the hard way by encoding it into the package name.
This would make it possible to directly address the two different versions from the same calling source file.
I think that if you truly want to solve the problem, you need to extend the definition of the fully qualified classname to include the notion of a breaking version reference. Kind of like what folks now sometimes do the hard way by encoding it into the package name.
This would make it possible to directly address the two different versions from the same calling source file.
I agree, but I believe the “shrinkage” would already reduce the problem substantially, and maybe more importantly, would make developers more careful about what they include as interface dependencies instead of as just implementation dependencies.
OSGi allowed you to specify in excruciating detail what dependencies you had, whether API (i.e you wanted to re-export types from another library) or not, and much more. Unfortunately, it became far, far more complex than just implementing a simple module system, so as most things from the era (early 2000's) it became a huge, complex beast no one wanted to touch anymore.
Then your app would explicitly be doing the impendance mismatch resolution (converting objects from one version of library to the other) when doing the library calls.
which someone would have to code in as that's not automatically possible all the time.
You're pretty much screwed in that case but that's kind of by design and the entire point of versioning, isn't it?
One thing is Scala plays fast and loose with backwards compatibility. So much so that akka actually prints out messages if they find jars with different versions. It's a pain in the arse.
Essentially OSGI is that. It is still a ballache tho, and slow to boot, so I would not recommend it.
Best bet it to be picky about dependencies that respect backward compatiblity or do name changes (like commons collections4)
Best bet it to be picky about dependencies that respect backward compatiblity or do name changes (like commons collections4)
[deleted]
Dependency conflicts is a fundamental issue of mature ecosystems, linux especially included.
The issue is one of granularity of dependency: it can't be calculated from the code and dependency graph easily. Each class or function invocation has an associated metadata version, and something that tracks all the sub-ones, with compatibility matrices across the major versions of the library?
As in, a dependency / linked library has a new version. How do you know if that can be safely updated in your code? All you have fundamentally is a coarse version number for the entire library, it's types/classes, it's functions/procedures/methods/signatures. Does anything indicate which signatures changed aside from compilers? Does anything mark which functions have new logic in them?
Yikes. That can't be maintained by humans. No language has dared to do something that would resolve to that level of compatibility analysis. Can you imagine the time involved?
Maybe there's simpler indicators. Git repo as a service might be able to use the repo history to track what parts of a library actually changed with some metadata file at a sufficiently granular level.
Currently, convention dictates that you use a new class name or namespace or something similar for "breaking" changes, or a major version number boost with some assumed "service life" for the previous library major version. You know, if they do that. But there's instances (one of the java bytcode emission libraries IIRC) where the api remainined the same but was a breaking change.
Nothing exists to help a library maintainer be aware of what will be a breaking change. At granular levels that is inherent to the language design. At best, you have unit tests as the actually deep introspection of the interface and expected responses. But that is per-project.
As mentioned, you can also shade and dynamically renamespace a library. That almost is the solution, but shared libraries are a thing, and a if you have 10 libraries each shaded-using a common util library (ahem, slf4j, first item in the blog post), then that's precious ram wasted, even in modern RAM sizes. With three-deep versions like 4.0.7 or something similar, how would a build system know that it could safely reuse a shaded version? It basically can't. There's no language constructs for saying that it can.
To some degree I believe this a failure, in the case of Java, of some sort of overarching organization that tracks commons libraries, and while maybe not placing them in the language standard library, recommending best practices around those libraries across known usage patterns so library import/compiling can be gradually optimized, or common conflicts alleviated. It's almost like security patching to some degree. Maven and its repos aren't up to the task.
You have a new language? Likely nothing in it will killer app it, instead what makes modern new languages succeed isn't just novel language features, it's community and herding cats. It's what Zig just learned from one tweet, what Lisp's community never really learned for what otherwise should be the "ultimate" language. It's how Rust has made progress, and maybe Go too.
I wonder if in 200 years if there will actually be mature, stable languages with mature, stable libraries that haven't needed to change for a couple decades.
Anyway, "compatibility" is a hard hard hard problem.
The issue is one of granularity of dependency: it can't be calculated from the code and dependency graph easily. Each class or function invocation has an associated metadata version, and something that tracks all the sub-ones, with compatibility matrices across the major versions of the library?
As in, a dependency / linked library has a new version. How do you know if that can be safely updated in your code? All you have fundamentally is a coarse version number for the entire library, it's types/classes, it's functions/procedures/methods/signatures. Does anything indicate which signatures changed aside from compilers? Does anything mark which functions have new logic in them?
Yikes. That can't be maintained by humans. No language has dared to do something that would resolve to that level of compatibility analysis. Can you imagine the time involved?
Maybe there's simpler indicators. Git repo as a service might be able to use the repo history to track what parts of a library actually changed with some metadata file at a sufficiently granular level.
Currently, convention dictates that you use a new class name or namespace or something similar for "breaking" changes, or a major version number boost with some assumed "service life" for the previous library major version. You know, if they do that. But there's instances (one of the java bytcode emission libraries IIRC) where the api remainined the same but was a breaking change.
Nothing exists to help a library maintainer be aware of what will be a breaking change. At granular levels that is inherent to the language design. At best, you have unit tests as the actually deep introspection of the interface and expected responses. But that is per-project.
As mentioned, you can also shade and dynamically renamespace a library. That almost is the solution, but shared libraries are a thing, and a if you have 10 libraries each shaded-using a common util library (ahem, slf4j, first item in the blog post), then that's precious ram wasted, even in modern RAM sizes. With three-deep versions like 4.0.7 or something similar, how would a build system know that it could safely reuse a shaded version? It basically can't. There's no language constructs for saying that it can.
To some degree I believe this a failure, in the case of Java, of some sort of overarching organization that tracks commons libraries, and while maybe not placing them in the language standard library, recommending best practices around those libraries across known usage patterns so library import/compiling can be gradually optimized, or common conflicts alleviated. It's almost like security patching to some degree. Maven and its repos aren't up to the task.
You have a new language? Likely nothing in it will killer app it, instead what makes modern new languages succeed isn't just novel language features, it's community and herding cats. It's what Zig just learned from one tweet, what Lisp's community never really learned for what otherwise should be the "ultimate" language. It's how Rust has made progress, and maybe Go too.
I wonder if in 200 years if there will actually be mature, stable languages with mature, stable libraries that haven't needed to change for a couple decades.
Anyway, "compatibility" is a hard hard hard problem.
A good middleground is Kotlin. You get some of the nice features / syntax from Java without the problems. While Scala is actually a way more powerful language, Kotlin is more than good enough for most real world tasks and the tooling is so much better.
Exactly, you might even go as far as to say that Kotlin exists because the people at Jetbrains looked at and dismissed Scala as just not what they were looking for in a language. And then they went on to develop Kotlin instead.
Kotlin is unique in the sense that the language originated from a company whose primary business it is to provide developer tooling and IDEs (intellij). They know a thing or two about what developers like and appreciate in their products.
It shows. This language is very nice to use for programmers. Lot's of clever syntax that minimizes boiler plate. Lot's of clever IDE support. Lot's of convenient features. Good build tooling. And so on. In contrast, Scala was always a bit all over the place. Lot's of different takes on how to do things; not all of them very successful in retrospect, tooling was a bit iffy, and so on.
It's the reason Kotlin got popular with Android developers early on because it provided a massive improvement over plain Java and sort of worked as a drop in replacement and was easy to switch to. As soon as Kotlin became available (pre 1.0), the Android community was all over it because at the time they were stuck with a pretty outdated Java language version. It did not take long for Google to make it the language of choice and start providing lot's of Kotlin focused updates to their SDK.
For the same reason, it got popular with Java backend developers early on. It doesn't really matter what Java backend framework you use; Kotlin is a drop in replacement for Java and the chances are pretty good that your framework of choice already has extensive Kotlin support in the form of Kotlin DSLs, extension functions, etc. That's certainly true for Spring/Spring Boot, Quarkus, and most other mainstream server side Java frameworks you can name.
The comparison with Scala is fair because a lot of Kotlin libraries are inspired by work in the Scala community. Additionally, it seems a lot of former Scala developers are now doing a lot of Kotlin. For better or for worse, it seems to compete pretty effectively with Scala. Either language of course is a pretty big improvement over Java; even with the improvements that Oracle has been trickling in over the last few years.
Kotlin is unique in the sense that the language originated from a company whose primary business it is to provide developer tooling and IDEs (intellij). They know a thing or two about what developers like and appreciate in their products.
It shows. This language is very nice to use for programmers. Lot's of clever syntax that minimizes boiler plate. Lot's of clever IDE support. Lot's of convenient features. Good build tooling. And so on. In contrast, Scala was always a bit all over the place. Lot's of different takes on how to do things; not all of them very successful in retrospect, tooling was a bit iffy, and so on.
It's the reason Kotlin got popular with Android developers early on because it provided a massive improvement over plain Java and sort of worked as a drop in replacement and was easy to switch to. As soon as Kotlin became available (pre 1.0), the Android community was all over it because at the time they were stuck with a pretty outdated Java language version. It did not take long for Google to make it the language of choice and start providing lot's of Kotlin focused updates to their SDK.
For the same reason, it got popular with Java backend developers early on. It doesn't really matter what Java backend framework you use; Kotlin is a drop in replacement for Java and the chances are pretty good that your framework of choice already has extensive Kotlin support in the form of Kotlin DSLs, extension functions, etc. That's certainly true for Spring/Spring Boot, Quarkus, and most other mainstream server side Java frameworks you can name.
The comparison with Scala is fair because a lot of Kotlin libraries are inspired by work in the Scala community. Additionally, it seems a lot of former Scala developers are now doing a lot of Kotlin. For better or for worse, it seems to compete pretty effectively with Scala. Either language of course is a pretty big improvement over Java; even with the improvements that Oracle has been trickling in over the last few years.
> They know a thing or two about what developers like and appreciate in their products.
Hah, I wish that was true. Looking at the last releases and the new UI which is about to come I highly doubt that is true. Although adding flashy new features instead of fixing bugs in a "visual" IDE is different than developing a programming language.
Hah, I wish that was true. Looking at the last releases and the new UI which is about to come I highly doubt that is true. Although adding flashy new features instead of fixing bugs in a "visual" IDE is different than developing a programming language.
What do you mean exactly with "the last release"? I think Kotlin is on a good way and JetBrains is investing in the right things like the new compiler. There are also a lot of low-hanging fruits in the Kotlin YouTrack issue tracker, but then again I accept that is better to focus on fundamental things like the compiler where every developer profits from.
It actually is. Now that IntelliJ has cut ties with the Evil Empire I would expect its adoption to grow faster. But I must say that a year ago I could find no Kotlin _backend_ positions in the Bay Area.
On the technical side
* I don't like the idiomatic Kotlin approach to concurrency. Its coroutines are more difficult and unusual than typical Future-based libraries in other JVM languages.
* I'm not convinced null safety is a big enough question to justify multiple cryptic operators.
Personally I dread the demise of Scala. The Haskell lovers and the Akka license changers are certainly squeezing regular developers out big time. Databricks built a C++ engine, Rust is increasingly popular in other new OSS query engines. Those trends don't bode well at at all. Java is more expressive than golang but I'd rather use something more modern than either of them.
On the technical side
* I don't like the idiomatic Kotlin approach to concurrency. Its coroutines are more difficult and unusual than typical Future-based libraries in other JVM languages.
* I'm not convinced null safety is a big enough question to justify multiple cryptic operators.
Personally I dread the demise of Scala. The Haskell lovers and the Akka license changers are certainly squeezing regular developers out big time. Databricks built a C++ engine, Rust is increasingly popular in other new OSS query engines. Those trends don't bode well at at all. Java is more expressive than golang but I'd rather use something more modern than either of them.
> I'm not convinced null safety is a big enough question to justify multiple cryptic operators.
I am. I've been working on a large c++ project recently and almost all the crashes in it would be solved by compiler- enforced null safety. Kotlin's null-safe operators don't look cryptic to me, they're more or the less the same as those from C#, Typescript etc. OTOH Java seems to go out of its way to make it hard to write null-safe code.
I am. I've been working on a large c++ project recently and almost all the crashes in it would be solved by compiler- enforced null safety. Kotlin's null-safe operators don't look cryptic to me, they're more or the less the same as those from C#, Typescript etc. OTOH Java seems to go out of its way to make it hard to write null-safe code.
Honestly Java is lately the best it's ever been, at least for backend services. So much power in the frameworks (ok Spring Boot) with so many powerful libraries and tools and available apis.
You really feel like you can do anything with it lately.
You really feel like you can do anything with it lately.
I actually think Scala is in the best position it's ever been.
There is a commitment to making the language simpler, easier and cleaner.
On the backend, ZIO (https://zio.dev) is the best concurrency library on any platform. On the frontend you have really interesting Scala.js projects like Laminar (https://laminar.dev).
The biggest issue really is the tooling. SBT is simply awful.
There is a commitment to making the language simpler, easier and cleaner.
On the backend, ZIO (https://zio.dev) is the best concurrency library on any platform. On the frontend you have really interesting Scala.js projects like Laminar (https://laminar.dev).
The biggest issue really is the tooling. SBT is simply awful.
I agree with a lot of the criticism in the article, but also agree with this idea that Scala is in the best position it has ever been. Core Scala is migrating to Scala3 (will take a few years) and the scala team had the courage to take on the rough edges. The Typelevel community (FP side) has a whole ecosystem which is maturing into something really nice. Akka pulled the ripcord on licensing so everyone knows where they stand.
Across the board the language and environment is stabilizing. Most of the (correct) criticisms expressed in this article are either 1. An expression that dependency management remains really hard as dependencies and ecosystems grow 2. An artifact of the fact that early scala projects relied heavily on borrowing from java to bootstrap and it caused a snarl of dependencies. On the latter, I see a decline in snarl overtime.
It is fair to say that Rust and Go have a really awesome toolchain experience and are setting the standard (though I wonder if the problems of being "old" and having boatloads of libraries haven't yet set in). SBT nominally has a similar experience but it's definitely slower and somehow less intuitive. Hoping to see more work in this area and I think Mill + SBT "competing" + BSP and bloop opening the door for more innovation will allow for quick progress.
Across the board the language and environment is stabilizing. Most of the (correct) criticisms expressed in this article are either 1. An expression that dependency management remains really hard as dependencies and ecosystems grow 2. An artifact of the fact that early scala projects relied heavily on borrowing from java to bootstrap and it caused a snarl of dependencies. On the latter, I see a decline in snarl overtime.
It is fair to say that Rust and Go have a really awesome toolchain experience and are setting the standard (though I wonder if the problems of being "old" and having boatloads of libraries haven't yet set in). SBT nominally has a similar experience but it's definitely slower and somehow less intuitive. Hoping to see more work in this area and I think Mill + SBT "competing" + BSP and bloop opening the door for more innovation will allow for quick progress.
For me the big win with Go, is its so easy to get from new project -> first working test.
I think there installation of the required tooling is very easy and just works, unlike other languages where you can spend a lot of time just getting all of that initial stuff setup. Also upgrading the tool chain is very easy as well.
I think there installation of the required tooling is very easy and just works, unlike other languages where you can spend a lot of time just getting all of that initial stuff setup. Also upgrading the tool chain is very easy as well.
That's funny, because this is what I really like about Scala; how quick and easy it is to get a project started.
> sbt new scala/scala3.g8
will just create an empty project. If you don't even want to bother with a project, use use scala-cli or ammonite (http://ammonite.io/) to just start banging out code.
Even the upgrading of a project from Scala2 to Scala3 is a breeze, thanks to very good backwards compatibility of new library releases.
> sbt new scala/scala3.g8
will just create an empty project. If you don't even want to bother with a project, use use scala-cli or ammonite (http://ammonite.io/) to just start banging out code.
Even the upgrading of a project from Scala2 to Scala3 is a breeze, thanks to very good backwards compatibility of new library releases.
> The biggest issue really is the tooling. SBT is simply awful.
It's like they sat down and said "Maven has a bunch of problems. Let's fix none of them and introduce a few new ones."
It's like they sat down and said "Maven has a bunch of problems. Let's fix none of them and introduce a few new ones."
Agreed. Maybe the situation has changed now, but it also didn't help that sbt's DSL is so inconsistent.
Back 2 years ago, when I still used Scala, sbt had two ways to write build files, the "old" and "new" ways, both non-trivial except for the simplest cases, and when you were troubleshooting/debugging problems with your build, all the answers you found googling were for the other style (facepalm).
Back 2 years ago, when I still used Scala, sbt had two ways to write build files, the "old" and "new" ways, both non-trivial except for the simplest cases, and when you were troubleshooting/debugging problems with your build, all the answers you found googling were for the other style (facepalm).
What kills me is IJ underlines all my sbt files in red.
Ouch.
I remember back when Scala was still on version 1, the official/recommended IDE was Scala IDE, based on Eclipse. Eclipse was already a mess at that time, and people were abandoning it in droves even for Java work, but (bizarrely) Scala IDE was endorsed by Odersky.
Get this: refactoring -- critical for a language like Scala -- was totally broken on Scala IDE. Completely, unusably broken. Like, you changed the name of a function and the IDE inserted nonsensical garbage that didn't compile or even follow syntax rules everywhere. This situation went for long enough that most sane people migrated to IntelliJ. This was back then, no idea what the situation is now or whether Scala IDE still exists.
I remember back when Scala was still on version 1, the official/recommended IDE was Scala IDE, based on Eclipse. Eclipse was already a mess at that time, and people were abandoning it in droves even for Java work, but (bizarrely) Scala IDE was endorsed by Odersky.
Get this: refactoring -- critical for a language like Scala -- was totally broken on Scala IDE. Completely, unusably broken. Like, you changed the name of a function and the IDE inserted nonsensical garbage that didn't compile or even follow syntax rules everywhere. This situation went for long enough that most sane people migrated to IntelliJ. This was back then, no idea what the situation is now or whether Scala IDE still exists.
Sometimes when creating software that solves a hard problem, the author is so thrilled by all the little conceptual breakthroughs they experience along the way that they think the users of their software will enjoy it just as much as they did, so they write the software in such a way that the users have to make all the same conceptual breakthroughs in order to use it. SBT feels like that's what happened to it. It's completely inappropriate for a build tool. 99% of the people using a build tool shouldn't have to appreciate how hard it is to write a build tool.
I recommend to have a look at Mill. It's versatile, built on simple foundations, and implements many concepts from general-purpose build tools such as Bazel (but of course it was designed for Scala). It's easy to call it from various scripts too, and doesn't require you to design your project around your build tool.
At work we've used mill to first replace sbt and then also gradle in another project, and haven't looked back. It worked out-of-the-box for our JVM projects, and we trivially wrote custom "rules" for integrating cmake-based C++ projects into the build.
At work we've used mill to first replace sbt and then also gradle in another project, and haven't looked back. It worked out-of-the-box for our JVM projects, and we trivially wrote custom "rules" for integrating cmake-based C++ projects into the build.
granted ZIO is excellent.
Scala.js is a dead end that almost no one should be investing in. Who can honestly say that the best possible dev path for them (product/business) is to need Scala devs to do their JS frontend? Even just the economics of the pay-gap in those two skillsets is untenable. We've been through this before any number of times in JAVA, give up it's an awful choice no one will thank you for.
I'm also frustrated by how we seem to have managed to not only recreate the Spring problem with FP libraries (communities online will tell people to first go with their personal FP lib of choice as a "must have" for starting a project) but make it worse by also having competing 'factions' who argue about which one is better.
We're apparently aiming to recreate all the same mistakes JAVA started making which was the launchpad for Scala and other JVM language variants in the first place.
Scala.js is a dead end that almost no one should be investing in. Who can honestly say that the best possible dev path for them (product/business) is to need Scala devs to do their JS frontend? Even just the economics of the pay-gap in those two skillsets is untenable. We've been through this before any number of times in JAVA, give up it's an awful choice no one will thank you for.
I'm also frustrated by how we seem to have managed to not only recreate the Spring problem with FP libraries (communities online will tell people to first go with their personal FP lib of choice as a "must have" for starting a project) but make it worse by also having competing 'factions' who argue about which one is better.
We're apparently aiming to recreate all the same mistakes JAVA started making which was the launchpad for Scala and other JVM language variants in the first place.
I sincerely hope Scala.js isn't "dead". Though I know use by academics isn't the use case you imagined, Scala.js has very much been the right choice for me publishing interactive Open Educational Resources that can include all sorts of little simulations, models, and programmable games. It's not the sort of thing I'd have time to do in any other language, but via Scala.js (and a front end framework I wrote) I can put together something that (though it's scrappy because I rarely get time to add the polish) works well enough very fast.
Disclaimer I'm already a big fan of Scala, but I agree that the tooling around scala.js is lacking and the std lib is a rather large blob to ship around, especially when compared to alternative functional languages like ocaml.
However, I've been using the above mentioned laminar for my personal frontend project needs and it really is a unique approach to the 'reactive' frontend with no vdom actually using reactive streams to track what needs to be updated. The dsl is easy to read and write and i can actually read the underlying code. For me it's scaled well too large datasets generating svgs. I think it's worth the scala.js barrier to entry.
However, I've been using the above mentioned laminar for my personal frontend project needs and it really is a unique approach to the 'reactive' frontend with no vdom actually using reactive streams to track what needs to be updated. The dsl is easy to read and write and i can actually read the underlying code. For me it's scaled well too large datasets generating svgs. I think it's worth the scala.js barrier to entry.
> Who can honestly say that the best possible dev path for them (product/business) is to need Scala devs to do their JS frontend?
The ability to give a developer a feature and have them use the same language, domain model, error handling logic, business logic, serialisation codecs, tooling etc to implement it end-to-end is compelling to me.
And the number of developers who are seriously good at full-stack is far smaller than Scala ones.
The ability to give a developer a feature and have them use the same language, domain model, error handling logic, business logic, serialisation codecs, tooling etc to implement it end-to-end is compelling to me.
And the number of developers who are seriously good at full-stack is far smaller than Scala ones.
> We've been through this before any number of times in JAVA, give up it's an awful choice no one will thank you for.
Is it? Google uses it quite extensively, though they mostly have their shared business code in the form of a java library that is compiled to each target platform.
Is it? Google uses it quite extensively, though they mostly have their shared business code in the form of a java library that is compiled to each target platform.
Big agreement here.
Scala2 was a wonderful language, Scala 3 even more so; lots of corner cases have been removed and I even start to like the significant-whitespace-style.
ZIO and Typesafe (although I agree with the article; I could do with less drama) are simply amazing ecosystems. Libraries like Tapir and Quill seek their equal in other languages.
And even though sbt could be better it has been vastly improved in the last few years.
Scala2 was a wonderful language, Scala 3 even more so; lots of corner cases have been removed and I even start to like the significant-whitespace-style.
ZIO and Typesafe (although I agree with the article; I could do with less drama) are simply amazing ecosystems. Libraries like Tapir and Quill seek their equal in other languages.
And even though sbt could be better it has been vastly improved in the last few years.
> The biggest issue really is the tooling. SBT is simply awful.
This is backwards. The problem is that scala is simply awful. SBT just reflects the problems with scala. First and foremost, the authors of the scala language are either incapable of writing a decent build tool or they think that SBT is good enough. They have proven over many years that they do not prioritize the experience of developers actually writing code. Slow compile times are a much bigger drain on productivity than the superficial syntactical improvements that were made for scala 3.
The specific problems with sbt, needless complexity, inscrutable dsls, bloated code paths leading to slow start up times: these are all endemic to scala itself. The standard library is so badly organized that it takes 100s of milliseconds to load a simple hello world application: https://twitter.com/li_haoyi/status/1125674970829320193?cxt=.... Mill may be better than sbt in some ways, it's definitely worse in others but at the end of the day, if you are using either, you are stuck with scala and scala is very, very unlikely to ever get significantly better than it is today.
This is backwards. The problem is that scala is simply awful. SBT just reflects the problems with scala. First and foremost, the authors of the scala language are either incapable of writing a decent build tool or they think that SBT is good enough. They have proven over many years that they do not prioritize the experience of developers actually writing code. Slow compile times are a much bigger drain on productivity than the superficial syntactical improvements that were made for scala 3.
The specific problems with sbt, needless complexity, inscrutable dsls, bloated code paths leading to slow start up times: these are all endemic to scala itself. The standard library is so badly organized that it takes 100s of milliseconds to load a simple hello world application: https://twitter.com/li_haoyi/status/1125674970829320193?cxt=.... Mill may be better than sbt in some ways, it's definitely worse in others but at the end of the day, if you are using either, you are stuck with scala and scala is very, very unlikely to ever get significantly better than it is today.
On any platform?
It has the ability to make real-world concurrency scenarios trivial e.g.
* 3 fibers - each fetches from remote storage, local storage and in-memory cache.
* Race them, kill the two slowest and give me the result.
* Free the resources safely including if any of the connections fails for an unforeseen reason.
That's a few lines in ZIO. Pain to get working properly in Java, Rust, Go, C++ at least.
* 3 fibers - each fetches from remote storage, local storage and in-memory cache.
* Race them, kill the two slowest and give me the result.
* Free the resources safely including if any of the connections fails for an unforeseen reason.
That's a few lines in ZIO. Pain to get working properly in Java, Rust, Go, C++ at least.
It may be the best on any platform outside of the BEAM, but there are a lot of correlating factors needed to create the ideal concurrency platform that you simply can't do without building them from the ground up.
It's why almost anything outside the BEAM can't make that claim.
It's why almost anything outside the BEAM can't make that claim.
True, BEAM is a platform on its own. Scala can use Akka which is also awesome, but doesn't have all the nice things builtin like BEAM.
I guess a merge of Scala as the language (because honestly, Erlang & co suck) and BEAM as the platform would be awesome!
I guess a merge of Scala as the language (because honestly, Erlang & co suck) and BEAM as the platform would be awesome!
A statically-typed language running on BEAM? Sounds like Gleam: https://gleam.run/
(Disclaimer: I haven't used Gleam, I just know it exists.)
(Disclaimer: I haven't used Gleam, I just know it exists.)
I think as a Scala developer, my expectations/demands can't be matched by Gleam unfortunately. But if it could, then yes!
This is actually trivial in Go as well, with a context (cancellation) and a WaitGroup or channel (waiting for the first one to finish).
Go fails at the error-handling and resource-safety part. The compiler does not cover you properly.
The fact that the compiler doesn't cover that automatically doesn't mean Go fails at it, as it has very good primitives for handling them.
Error handling and deferring for resource closure work just fine.
Sure you could say "but the compiler doesn't guarantee it". But that's not much of a point if it's not a real problem in practice.
Error handling and deferring for resource closure work just fine.
Sure you could say "but the compiler doesn't guarantee it". But that's not much of a point if it's not a real problem in practice.
> The fact that the compiler doesn't cover that automatically doesn't mean Go fails at it
But that's exactly what OP was talking about. Maybe for you that doesn't mean Go fails here, but for (us) Scala developers it definitely feel like Go fails us. We want a language that fails at compiletime in as many cases as possible.
> But that's not much of a point if it's not a real problem in practice.
Maybe not for you. For me it is!
But that's exactly what OP was talking about. Maybe for you that doesn't mean Go fails here, but for (us) Scala developers it definitely feel like Go fails us. We want a language that fails at compiletime in as many cases as possible.
> But that's not much of a point if it's not a real problem in practice.
Maybe not for you. For me it is!
I agree it's fine to have different taste, as I mentioned in another reply to you.
But it's the difference between whether this statement is objective, or subjective.
> is the best concurrency library on any platform
But it's the difference between whether this statement is objective, or subjective.
> is the best concurrency library on any platform
Fair enough, that sentence is a bit over the top. I personally agree, but it is subjective and sounds like a fact.
Not a real problem in practice is just another way of saying rare. But given enough scale and enough time, rare things do happen, and they cost inordinately more programmer effort to chase down. I actually don’t mind if the compiler lets me ship very dumb bugs: those will be auto-rolled back out of production in seconds. It’s the subtle stuff that kills me.
Error handling and Go doesn’t mix well.
That's a matter of opinion. Many, me included, very much like the current, very explicit, approach.
I understand why people who like monadic constructs don't like it though.
I understand why people who like monadic constructs don't like it though.
I don’t know — I don’t claim that algebraic datatypes are the only proper way to handle errors, I’m okay with exceptions as well (even checked ones). But what go has is only very slightly better than C’s attempt, so I’m not sure it is that subjective.
I think the presence of multiple return values and the ability to easily use complex types for errors make a huge difference (adding wrapping messages, context, etc.).
I agree algebraic data types could improve this. I don't think monadic result types or exceptions would be an improvement.
I agree algebraic data types could improve this. I don't think monadic result types or exceptions would be an improvement.
I think maybe you've misread the intent.
I do not want to wait for the three fibers to finish. I want the whole process to stop the minute any of them have returned i.e. get me my data as quick as possible no matter its source.
I do not want to wait for the three fibers to finish. I want the whole process to stop the minute any of them have returned i.e. get me my data as quick as possible no matter its source.
This is exactly the kind of problem that 0.000324% of us are having while being productive in Java/Rust/Go/C++ ... ;)
Thats the thing with Scala, they are solving important problems. It is not spending time on useless problem like performant build system. I mean code is gonna compile eventually, if not today maybe tomorrow. But complex problem like described above will not be solved unless someone make a decent framework for it.
In the last 10 years every team/company I have been working in had to deal with at least one of these problems.
Good for you if you only ever have to work with single threaded applications, but for most of us the reality of modern software development is different.
It definitely is. You can even see it by looking at how the languages market themselves, claiming to make concurrency easy etc.
I find that one of the best things about using a managed runtime such as the JVM is the ability to get stack traces when things go wrong. When debugging, it is a considerable time saver to be able to determine the causality chain that lead to a specific failure.
Unfortunately, all libraries that abstract concurrency on an application-level break the ability to get meaningful stack traces. At least all the ones I know of, including ZIO, Akka, Monix, plain Futures, etc. I know that there is tooling to counteract that (such as the abstractions used in distributed tracing), but that's again on the language level.
In my experience, for all but the most advanced applications, the debuggability advantages of using linear code outweigh the performance advantages gained by abstracting over execution contexts. Thus, I would posit that concurrency is best dealt with on the platform, not the language level, especially when starting a project.
Of course there are some situations where a library can make some concurrency task appear trivial, but as long as there is no good tooling, the time saved using beautiful abstractions tends to be paid back 5-fold when those abstraction break (which they often do as an application grows).
Unfortunately, all libraries that abstract concurrency on an application-level break the ability to get meaningful stack traces. At least all the ones I know of, including ZIO, Akka, Monix, plain Futures, etc. I know that there is tooling to counteract that (such as the abstractions used in distributed tracing), but that's again on the language level.
In my experience, for all but the most advanced applications, the debuggability advantages of using linear code outweigh the performance advantages gained by abstracting over execution contexts. Thus, I would posit that concurrency is best dealt with on the platform, not the language level, especially when starting a project.
Of course there are some situations where a library can make some concurrency task appear trivial, but as long as there is no good tooling, the time saved using beautiful abstractions tends to be paid back 5-fold when those abstraction break (which they often do as an application grows).
> Unfortunately, all libraries that abstract concurrency on an application-level break the ability to get meaningful stack traces.
This is completely false. Years ago we (7mind) added async stack traces to ZIO. Now both Cats and ZIO support them.
This is completely false. Years ago we (7mind) added async stack traces to ZIO. Now both Cats and ZIO support them.
That sounds like RxJS race(), and given that it's JS there's often no cleanup needed (and if there is RxJS has easy ways of doing that as well).
https://www.learnrxjs.io/learn-rxjs/operators/combination/ra...
https://www.learnrxjs.io/learn-rxjs/operators/combination/ra...
No backpressure in RxJS.
It's trivial in Haskell, a bit hard in Rust, really hard in Java, and trivial to get a non-working implementation and declare it flawless on C++. I never tried it in Go.
This will make it trivial in Java: https://openjdk.org/jeps/428
Cats effect can do the same
> Maybe this is just me getting older (going to turn 40 soon). Maybe all programming is terrible. I’ve actually started to read Java newsletters, maybe Spring isn’t that bad, I’m also having affectionate memories of JavaScript and Python, and thinking about having a plan B in case this programming thing doesn’t work out
The older I get the more this rings true. I've had several false starts with fancy new languages and consistently yearn for the simplicity (relatively) and lack of choice the old times had. I've been programming a lot of personal projects in C because of that. Rust is cool but too much headache and still too "fresh" to be more than just an academic exercise for me. Go is the same, except im actually insulted at how limited I am with it. etc. Yea, this is probably me getting old. But I like to have one or two languages I can get things done with it. I've been programming Python since the early 00s in one form or another betting on it replacing Perl, and C has always had a charm to it C++ could not give.
The older I get the more this rings true. I've had several false starts with fancy new languages and consistently yearn for the simplicity (relatively) and lack of choice the old times had. I've been programming a lot of personal projects in C because of that. Rust is cool but too much headache and still too "fresh" to be more than just an academic exercise for me. Go is the same, except im actually insulted at how limited I am with it. etc. Yea, this is probably me getting old. But I like to have one or two languages I can get things done with it. I've been programming Python since the early 00s in one form or another betting on it replacing Perl, and C has always had a charm to it C++ could not give.
In the end, having a 'more expressive' language isn't the key competitive advantage. At least, I can't recall when a company seems to have significantly outperformed a competitor because they used a 'fancier' programming language. Yes, of course, the blogposts by PaulG and how reddit started, but I'm not sure that reddit is succesful because they programmed it in lisp at first.
Twitter specifically was designed in a time when RoR was really popular, but I'm not sure it worked _because_ it was built in RoR, and we all remember how twitter still exists simply by the grace that they managed to rewrite themselves away from the fail whale before competitors woke up to match their feature set.
Now it's written in scala and, to me anyway, I see hundreds of developers and I'm not _at all_ impressed by their development momentum, even though it's written in scala.
So, if that isn't the competitive advantage, why go for it in the first place? At least blue collar languages have much, much larger pools of competent programmers to select from, which is an objective, convenient upside any manager can understand.
Twitter specifically was designed in a time when RoR was really popular, but I'm not sure it worked _because_ it was built in RoR, and we all remember how twitter still exists simply by the grace that they managed to rewrite themselves away from the fail whale before competitors woke up to match their feature set.
Now it's written in scala and, to me anyway, I see hundreds of developers and I'm not _at all_ impressed by their development momentum, even though it's written in scala.
So, if that isn't the competitive advantage, why go for it in the first place? At least blue collar languages have much, much larger pools of competent programmers to select from, which is an objective, convenient upside any manager can understand.
> So, if that isn't the competitive advantage, why go for it in the first place? At least blue collar languages have much, much larger pools of competent programmers to select from, which is an objective, convenient upside any manager can understand.
I think its like Haskell, Rust, Go, Erlang, etc. These languages are extremely useful in the microcosm of places where they excel. Rust when you absolutely need to insure memory safety, Go when you need near-C speeds but a simple to use concurrency system, Haskell for rigid typing, Erlang for high availability, etc. The problem is the dead average developer looks at these, and sees these high flying companies doing cool things in it, and then decides "wow I should write everything in this - it's the future!"
Scala is the same way. It's not objectively better than a modern java in any way which might be taken as fighting words. But foregoing a lot of developer history you gain the power to reason about a very, very small subset of programming easier at the cost of speed, time, etc. For a company like a twitter with a very specific use case for this it made sense. Especially since at the time twitter switch from RoR to Scala, Python and it's concurrency platform didn't exist. However, I would speculate if they switched today they would've almost certainly gone to Python which would have been a much less "cool" switch and probably not even made the news cycle.
I think its like Haskell, Rust, Go, Erlang, etc. These languages are extremely useful in the microcosm of places where they excel. Rust when you absolutely need to insure memory safety, Go when you need near-C speeds but a simple to use concurrency system, Haskell for rigid typing, Erlang for high availability, etc. The problem is the dead average developer looks at these, and sees these high flying companies doing cool things in it, and then decides "wow I should write everything in this - it's the future!"
Scala is the same way. It's not objectively better than a modern java in any way which might be taken as fighting words. But foregoing a lot of developer history you gain the power to reason about a very, very small subset of programming easier at the cost of speed, time, etc. For a company like a twitter with a very specific use case for this it made sense. Especially since at the time twitter switch from RoR to Scala, Python and it's concurrency platform didn't exist. However, I would speculate if they switched today they would've almost certainly gone to Python which would have been a much less "cool" switch and probably not even made the news cycle.
I think one issue is use cases that fall in-between. For example I use a lot of Python, but also need statically compiled, safe and solid language, with large ecosystem, with great Python interop. What do I choose?
In practice the answer seems to be C++, maybe Rust. I'd happily use a "simpler" language like Go, Java or Nim, but something doesn't quite match the spec.
I think, unsurprisingly, languages are designed around common use cases, but the uncommon ones are there too.
In practice the answer seems to be C++, maybe Rust. I'd happily use a "simpler" language like Go, Java or Nim, but something doesn't quite match the spec.
I think, unsurprisingly, languages are designed around common use cases, but the uncommon ones are there too.
I dunno, Haskell, sure, but Rust is just all around better C++... memory safety is just plainly less bugs and that's always desirable
> Python which would have been a much less "cool" switch and probably not even made the news cycle.
Very much doubt it re: Python. Performance, difficult to reason about, and lack of static typing all come to mind.
I agree that modern Java is competitive now, but it probably wasn't when they picked Scala.
Very much doubt it re: Python. Performance, difficult to reason about, and lack of static typing all come to mind.
I agree that modern Java is competitive now, but it probably wasn't when they picked Scala.
seriously. when they make me twitter cto for a day, my one change would be a public graph of build times (as a proxy for 'how long are backend devs waiting for builds')
I suspect this would be deeply embarrassing + would lead to change
in my (limited) experience, large scala codebases are not productive
scala adoption was all like 12 years ago and driven by bored developers looking for a brain teaser / resume builder. same trend as companies like linkedin / uber, who have no reason to invent infra, contributing a bunch of half-baked java projects to apache
I suspect this would be deeply embarrassing + would lead to change
in my (limited) experience, large scala codebases are not productive
scala adoption was all like 12 years ago and driven by bored developers looking for a brain teaser / resume builder. same trend as companies like linkedin / uber, who have no reason to invent infra, contributing a bunch of half-baked java projects to apache
> a bunch of half-baked java projects to apache
Like Kafka and Samza?
Like Kafka and Samza?
fair point there are some good ones
In my experience, companies who chose Scala did enjoy a competitive advantage. Almost no bugs in production and predictable velocity. No more "not sure what this will break". In Scala projects I worked I almost never encountered any surprises except on boundaries (Scala<>Message broker) and etc.
I saw projects (non-Scala) come to almost a complete stop from velocity perspective, because engineers were afraid to change old code. This resulted in many iterations and a lot of slow testing until changes were delivered. In my opinion, it can easily impact business side of things.
I saw projects (non-Scala) come to almost a complete stop from velocity perspective, because engineers were afraid to change old code. This resulted in many iterations and a lot of slow testing until changes were delivered. In my opinion, it can easily impact business side of things.
Around 8 years ago we chose Scala for some random microservice, because there was ONE guy in the team that loved Scala and wanted to do something with it. I said, sure go for it, it will be interesting to test the technology. After he implemented the microservice, it was rock solid for like 5 years. Said dev left 3 years later after implementing the service. Two years after he left, we needed to do something to the microservice... but nobody knew Scala in the team, so we have one or two "brave" guys who struggled to modify the Scala code.
The same thing happened years later in another startup in Elixir. I arrived to this startup and there was some random microservice that someone had implemented in Elixir because it was "the new cool language that solved all scalability issues". Again, the person that implemented it had left years ago, so nobody knew anything about Elixir or the microservice. Because I've dabbed with Elixir for fun, I volunteered to work on it. In the end we decided to supersede it.
I've learned to stay with boring technology. For me the sweet spot of productivity and team versatility is TypeScript and Javascript. Using these two technologies devs can do backend, frontend and mobile. The only thing missing is good bindings for Machine Learning.
The same thing happened years later in another startup in Elixir. I arrived to this startup and there was some random microservice that someone had implemented in Elixir because it was "the new cool language that solved all scalability issues". Again, the person that implemented it had left years ago, so nobody knew anything about Elixir or the microservice. Because I've dabbed with Elixir for fun, I volunteered to work on it. In the end we decided to supersede it.
I've learned to stay with boring technology. For me the sweet spot of productivity and team versatility is TypeScript and Javascript. Using these two technologies devs can do backend, frontend and mobile. The only thing missing is good bindings for Machine Learning.
Sorry, but those two stories sound like dream outcomes. A more typical outcome is a service that is never quite right, needs bug fixes every release, requires a code change for every minor change in the system around it, and basically serves as a jobs program for engineers. Somebody nails a service so well that it does its job quietly for years with no further work? I don't care your code is written in Aramaic and causes other programmers' heads to bubble and explode, please stay on my team and give me another service just like it.
Two services each implemented by a single developer operated without problems for multiple business cycles and this is something to avoid?
How does the effort of tweaking them in an unfamiliar language years later stack up against the effort they would have required otherwise?
How does the effort of tweaking them in an unfamiliar language years later stack up against the effort they would have required otherwise?
it moves money to the wrong people
When Scala was "hot", it was embraced by very good programmers. The complexity of the language sort of demanded it.
Thus, the stuff they wrote were well written.
After they leave, nobody can improve it or change it. (See sibling reply).
It's the people, not the language, that produces good software.
Thus, the stuff they wrote were well written.
After they leave, nobody can improve it or change it. (See sibling reply).
It's the people, not the language, that produces good software.
> When Scala was "hot", it was embraced by very good programmers. The complexity of the language sort of demanded it.
And reverse of that worked for Perl, then PHP, then JS (and arguably also Python/Ruby)
And reverse of that worked for Perl, then PHP, then JS (and arguably also Python/Ruby)
I'd encourage you to try Go or Rust, great ecosystems, great communities and lots of problems of programming languages of the 2000s are solved in much saner ways (dependency management, type checking, etc). There has been tremendous progress in programming languages in the last 20 years, it would be a shame to not learn about them and be super excited about them.
Rust and golang are not really in the same space. Rust is more of a C++ competitor, while golang is somewhere between python/ruby and Java/C#. Furthermore, there really isn't anything that golang does that Java or C# don't, but the latter do it in a much more saner way, especially Java now with Loom on the way. Unless you really need to compile to binaries, but both ecosystems are getting solutions in the works (GraalVM and Native AOT).
Sure, Java is going to take off and rule the world ....
Not sure if this is the joke, but it pretty much already does.
It was meant to be sarcastic, but I can see how you might think that it could be. I’ve never written a line of Java in my career but it’s probably more widespread in other parts of the industry.
I haven’t heard a developer being excited about writing Java in a long time.
I haven’t heard a developer being excited about writing Java in a long time.
I'd say Spring is kinda bad, but maybe not so much. But the JPQL and Hibernate parts are very bad and should be avoided for any serious work. Hibernate was made for a time with longer lived server-side objects, not today's workloads.
I wrote scala for six years and was on the team to first deploy akka in production. I've seen Json libraries come and go while also struggling to read files written with OO and FP patterns intermixed. Scala can be beautiful but in practice it gets messy.
Switched to Go four years ago and I've never looked back. Go made programming fun again just like PHP did before either of them.
Switched to Go four years ago and I've never looked back. Go made programming fun again just like PHP did before either of them.
Still here having fun with PHP :)
PHP 8.2 isn't Haskell but the type system is reliable and usable. There are a few gotchas here and there, almost always due to backwards compatibility, but nothing like earlier versions, and IMHO not more than other popular languages.
PHP 8.2 isn't Haskell but the type system is reliable and usable. There are a few gotchas here and there, almost always due to backwards compatibility, but nothing like earlier versions, and IMHO not more than other popular languages.
> Switched to Go four years ago and I've never looked back. Go made programming fun again just like PHP did before either of them.
My guess is this due to being actually be able to focus on the problem, instead of being distracted by type systems, language features, and deciding which of those features would actually be good to solve the problem?
If yes, then I would feel the same. Problem solving is the fun part of coding, and it makes me happy whenever I reach my actual goal - with whatever language is used. Being able to play around with language features to solve a problem mroe efficiently or elegantly can be fun too. But it's often more so if one is the original author of that software. If one is just a contributor then having to learn and understand extra technology that distracts one from actually solving the deemed problem can make tasks a lot less fun.
My guess is this due to being actually be able to focus on the problem, instead of being distracted by type systems, language features, and deciding which of those features would actually be good to solve the problem?
If yes, then I would feel the same. Problem solving is the fun part of coding, and it makes me happy whenever I reach my actual goal - with whatever language is used. Being able to play around with language features to solve a problem mroe efficiently or elegantly can be fun too. But it's often more so if one is the original author of that software. If one is just a contributor then having to learn and understand extra technology that distracts one from actually solving the deemed problem can make tasks a lot less fun.
to be fair, using Akka was mostly never fun, avoiding that improves the scala experience dramatically.
I was part of a team that processed really large files (hundereds of GB) in an Akka cluster. At that time Akka seemed like a clever choice to us, since we were Scala enthusiats and Akka was the framework of the day, but it took us many weeks to master (more or less) Akka. We could have done the same in a more robust and manageable way with Spring Batch in a fraction of the time.
Akka had a really steep learning curve for doing relatively boring things. Technically it was quite interesting, a from a business perspective it was a desaster.
Akka had a really steep learning curve for doing relatively boring things. Technically it was quite interesting, a from a business perspective it was a desaster.
> Scala can be beautiful but in practice it gets messy.
And, of course, you have a peer-reviewed article to support your statement?
And, of course, you have a peer-reviewed article to support your statement?
hmm, did we work together then? :) Always thought I was on the first team to deploy Akka in production.
I enjoyed Scala, but I enjoy F# much more. .NET Core is a healthy cross-plat ecosystem, many of the VSCode/F# tooling issues have been eliminated over the past few years (IntelliJ was really one of the core reasons I preferred Scala), plus Akka.NET has F# bindings. Come on in, the water's warm:
https://fsharp.org/learn/
https://getakka.net/
https://fsharp.org/learn/
https://getakka.net/
How long does it take for someone with about a decade's experience in C# to a point where they can write idiomatic F#?
5yrs ago I was roughly the same, depends how much you commit up front. I had minimal FP experience, so I bought "Domain Modeling Made Functional" [1] by Scott Wlaschin and used it for side projects / class libs first. Took about 6 months to experience the full mental shift.
Even if you eventually decide you can't commit a team to F#, it's highly worth it because doing at least one app in F# will vastly improve your C# and how you structure applications. [2] I personally just got addicted to the expressive power, it's hard to replicate with any other ecosystem given the full power of .NET under the hood. Giraffe is also a great place to start if you know ASP.NET Core. [3]
[1] https://www.amazon.com/dp/1680502549
[2] https://www.youtube.com/watch?v=US8QG9I1XW0
[3] https://github.com/giraffe-fsharp/Giraffe
Even if you eventually decide you can't commit a team to F#, it's highly worth it because doing at least one app in F# will vastly improve your C# and how you structure applications. [2] I personally just got addicted to the expressive power, it's hard to replicate with any other ecosystem given the full power of .NET under the hood. Giraffe is also a great place to start if you know ASP.NET Core. [3]
[1] https://www.amazon.com/dp/1680502549
[2] https://www.youtube.com/watch?v=US8QG9I1XW0
[3] https://github.com/giraffe-fsharp/Giraffe
I didn't have c# exp and it took me a month to feel "productive comfort", and less than 2 months until i felt "native comfort". I've been using it for about 2 years now.
That said I:
• had zero C# experience and it was the C# interop that caused me the most pain. Its easy now but I didn't grok how to properly pass arguments to overloaded C# methods (i kept messing up parenthesis, commas, and didn't pass argument names to tell f# the right function signature)
• have been coding for 8 years
• have functional lang experience with elixir and elm.
Now f# is my primary backend language.
That said I:
• had zero C# experience and it was the C# interop that caused me the most pain. Its easy now but I didn't grok how to properly pass arguments to overloaded C# methods (i kept messing up parenthesis, commas, and didn't pass argument names to tell f# the right function signature)
• have been coding for 8 years
• have functional lang experience with elixir and elm.
Now f# is my primary backend language.
Any experience in akka.net vs the Microsoft actor framework? (Orleans it's called I think?)
And get plagued with questions why not C#? No, thanks.
Scala was fun before Typelevel broke the community. I liked Scala when it was a pragmatic, hybrid FP-OOP language, with a powerful actor model implementation.
Now, OOP became a curse word, and if you do not do purely functional code with tagless-final and don’t know the definition of free monad by heart, you have no business writing Scala code (I like pure FP too, but if I want to write Haskell code, I can do it in Haskell), and the community drama with “typelevel/cats vs Scalaz” and “typelevel vs zio” was too much for me to handle. The new community is too toxic for me to continue writing anything in Scala.
The only bright point in Scala is lihaoyi’s ecosystem, which is sane enough to actually use, but it is too much to maintain for a single person, and it is losing momentum.
So I quit, and moved to Common Lisp, which is interesting and pragmatic enough.
Now, OOP became a curse word, and if you do not do purely functional code with tagless-final and don’t know the definition of free monad by heart, you have no business writing Scala code (I like pure FP too, but if I want to write Haskell code, I can do it in Haskell), and the community drama with “typelevel/cats vs Scalaz” and “typelevel vs zio” was too much for me to handle. The new community is too toxic for me to continue writing anything in Scala.
The only bright point in Scala is lihaoyi’s ecosystem, which is sane enough to actually use, but it is too much to maintain for a single person, and it is losing momentum.
So I quit, and moved to Common Lisp, which is interesting and pragmatic enough.
It's unfair to put that on Typelevel, but anyone can look up why it exists and judge for themselves.
However, Li Hayoi's libraries aren't a silver bullet. I could also argue something like "if I wanted to write exeception-throwing Java code, I can do it in Java." I use http4s/fs2/CE because of the better ergonomics, and I never needed to learn what a Free monad is.
However, Li Hayoi's libraries aren't a silver bullet. I could also argue something like "if I wanted to write exeception-throwing Java code, I can do it in Java." I use http4s/fs2/CE because of the better ergonomics, and I never needed to learn what a Free monad is.
I think one more problem with Scala, apart from the lack of stability and having to solve the language's problems instead of your application ones, is one of local maxima.
Most of the ecosystem uses monads. And the way most projects end up using monads is have "the one monad" that every function returns. ZIO is an example of that. Understandable, since the alternative is to have tons of different function colors.
However, since in that case the monad really is just a configurable semicolon semantic, you've just gone full circle and chosen a single global one.
And in that case, why not just choose a language where that semantic already is the core semicolon semantic of the language? You're living with a ton of complexity for very limited gain.
Most of the ecosystem uses monads. And the way most projects end up using monads is have "the one monad" that every function returns. ZIO is an example of that. Understandable, since the alternative is to have tons of different function colors.
However, since in that case the monad really is just a configurable semicolon semantic, you've just gone full circle and chosen a single global one.
And in that case, why not just choose a language where that semantic already is the core semicolon semantic of the language? You're living with a ton of complexity for very limited gain.
It seems (to me) less complex to have that as "just a library".
In most of my little projects, I don't use ZIO, I just have a tiny library I wrote years ago that lets me write stuff that works ok whether it's a Future[Seq] or a Seq[Future] or a Future[Seq[Future[Seq]]] underneath. https://github.com/wbillingsley/handy
If ZIO (or some other choice) were baked into the language, I'd be using their choice of async libnrary for everything whether I want to or not.
And I wouldn't be able to switch to the new-shiny-and-exciting-thing that comes out when I want to explore it because "sorry, X was what the designers chose when the language was written, so X it must be".
In Scala, I can use my little thing I'm familiar with, or I can try out ZIO, or Cats-Effect, or Akka Streams (before the licence change). I get to explore concepts very quickly and very easily without having to shift languages and learn a new set of build tools and syntax at the same time.
In most of my little projects, I don't use ZIO, I just have a tiny library I wrote years ago that lets me write stuff that works ok whether it's a Future[Seq] or a Seq[Future] or a Future[Seq[Future[Seq]]] underneath. https://github.com/wbillingsley/handy
If ZIO (or some other choice) were baked into the language, I'd be using their choice of async libnrary for everything whether I want to or not.
And I wouldn't be able to switch to the new-shiny-and-exciting-thing that comes out when I want to explore it because "sorry, X was what the designers chose when the language was written, so X it must be".
In Scala, I can use my little thing I'm familiar with, or I can try out ZIO, or Cats-Effect, or Akka Streams (before the licence change). I get to explore concepts very quickly and very easily without having to shift languages and learn a new set of build tools and syntax at the same time.
> why not just choose a language where that semantic already is the core semicolon semantic of the language?
The semicolon isn't semantic. A "semicolon" monad is essentially a single global context object. Most languages let anyone anywhere introduce a global context accessible from everywhere else. At least a monad lets you track it all.
The semicolon isn't semantic. A "semicolon" monad is essentially a single global context object. Most languages let anyone anywhere introduce a global context accessible from everywhere else. At least a monad lets you track it all.
It's not just context. It's also asynchronicity and error handling for example.
The semicolon semantic is how operations separated by semicolons (or newlines) are evaluated and how they impact the general state the program is in. Which is also what a monad's flatMap does, in a configurable way.
The semicolon semantic is how operations separated by semicolons (or newlines) are evaluated and how they impact the general state the program is in. Which is also what a monad's flatMap does, in a configurable way.
No, it is just context. Which context you choose in which part of your code is up to you. Somewhere I might choose ZIO. Elsewhere I might just choose an error-context. Or a state-context. Or a "let me accumulate some extra information while doing data-rprcessing"-context.
And it is always explicit when you are in a context and which one it is. This is really the strengths over languages where this concept is missing. Those languages will just merge and mushup contexts and you never know exactly which things are safe to use and not.
And it is always explicit when you are in a context and which one it is. This is really the strengths over languages where this concept is missing. Those languages will just merge and mushup contexts and you never know exactly which things are safe to use and not.
I know you can do it, the question is whether it's mainstream to do it, or whether in practice you end up with a single one in 95% of the cases.
Based on using it a bit and talking to many, more or less disillusioned, scala developers, my opinion is: it's not worth it.
It's fine for us to disagree though. There's enough programming languages and projects for everybody.
Based on using it a bit and talking to many, more or less disillusioned, scala developers, my opinion is: it's not worth it.
It's fine for us to disagree though. There's enough programming languages and projects for everybody.
It is very mainstream to do that.
Show me a project that is not just a small playground that uses either ZIO or cats-effect and does NOT use another context such as Either/Try or Option or List, ...
Show me a project that is not just a small playground that uses either ZIO or cats-effect and does NOT use another context such as Either/Try or Option or List, ...
1. Because different projects will want different monads
2. In my experience, having up-conversions between different monads is intuitive low-noise
2. In my experience, having up-conversions between different monads is intuitive low-noise
> Because different projects will want different monads
It doesn't look like that to me, based on how the ecosystem currently converges on a single one. I understand there may be some projects that do that, but if the majority converge, then it's still needles complexity.
However, I might be wrong. I've been an external observer for a while already.
It doesn't look like that to me, based on how the ecosystem currently converges on a single one. I understand there may be some projects that do that, but if the majority converge, then it's still needles complexity.
However, I might be wrong. I've been an external observer for a while already.
History proofs this wrong. Just look at it: first there were Scala Futures and Twitter Futures. Then there came Scalaz and Monix, later Cats-effect. Now ZIO also joined. And each library even brings different kind of effect types.
And all of that works, even in combination! This is as if you mix angular and react. Sure, you should try to not do that as much as possible, but the mere fact that you can do this in Scala is a sign of awesome language and library design that is far outstanding compared it the majority of other languages.
You could never come up with the "one true solution" from the very beginning.
And all of that works, even in combination! This is as if you mix angular and react. Sure, you should try to not do that as much as possible, but the mere fact that you can do this in Scala is a sign of awesome language and library design that is far outstanding compared it the majority of other languages.
You could never come up with the "one true solution" from the very beginning.
> You could never come up with the "one true solution" from the very beginning.
I think I can! I mean, that's what science is for, right?
I think I can! I mean, that's what science is for, right?
I'm not so sure. The problem is that the world is moving, including hardware, software, interfaces but also people and process. Languages have to optimize against a moving target. So naturally it's a good idea to optimize for something moving and not something static.
This is what makes Scala good. The language itself is not very complex actually, but it enables complex and powerful libraries.
This is what makes Scala good. The language itself is not very complex actually, but it enables complex and powerful libraries.
We are still in the phase where concepts are settling. Pretty sure nobody in a 100 years will think that Monads are a good idea.
> We are still in the phase where concepts are settling.
Yes of course concepts are still settling, and they always will be.
> Pretty sure nobody in a 100 years will think that Monads are a good idea.
Why? I for one am pretty sure monads will be a useful concept a hundred years from now.
What about functors, will that concept also be obsolete?
Yes of course concepts are still settling, and they always will be.
> Pretty sure nobody in a 100 years will think that Monads are a good idea.
Why? I for one am pretty sure monads will be a useful concept a hundred years from now.
What about functors, will that concept also be obsolete?
Listen, Monads are fine, Functors are fine, use them wherever and whenever you like. The problem I have with them is that they are making things explicit that are intuitively clear (Monads more than Functors). That is useful in some situations, but in most situations it is not, and just uses up precious brain capacity. If you go to the shop, you are not expecting someone at the entrance telling you that you have to pay for what you buy, and before paying, you are not telling the cashier that you are going to pay them now. You just do it.
Monads are like numbers. You can think they are not a good idea, but they are just a matter of fact and existence.
Also, in a 100 years maybe our brains will be completely different. How do you optimize your programming language for that? I don't think you can.
Also, in a 100 years maybe our brains will be completely different. How do you optimize your programming language for that? I don't think you can.
Given that our brains have been the same for a few thousand years, maybe I don't need to optimise for that.
Anyway, what we currently have as programming languages are all workarounds. Necessary for now, because how else would we program? But in the end we need to converge programming, math and logic, and once this is done, we will be ready for anything. And we won't need monads as a crutch, forced upon us by a type system. I am sure the concept of number will outlive the concept of monad in terms of popularity.
Anyway, what we currently have as programming languages are all workarounds. Necessary for now, because how else would we program? But in the end we need to converge programming, math and logic, and once this is done, we will be ready for anything. And we won't need monads as a crutch, forced upon us by a type system. I am sure the concept of number will outlive the concept of monad in terms of popularity.
> But in the end we need to converge programming, math and logic, and once this is done, we will be ready for anything. And we won't need monads as a crutch, forced upon us by a type system.
1. Math is filled to the brim with monads, it's just that mathematicians are necessarily specialists, and tend to think about things in terms of their applications to their specialties: they talk about closure operators or algebraic theories or formulas in a formal language, rather than monads as such. But that doesn't mean the monad structure isn't there.
2. Convergence between math and programming (which I agree is desirable) will almost certainly see type theory become more prominent, not less. There is some chance that programmers turn to constraint solvers or ML models for program verification instead, but if they do, mathematicians will not follow.
1. Math is filled to the brim with monads, it's just that mathematicians are necessarily specialists, and tend to think about things in terms of their applications to their specialties: they talk about closure operators or algebraic theories or formulas in a formal language, rather than monads as such. But that doesn't mean the monad structure isn't there.
2. Convergence between math and programming (which I agree is desirable) will almost certainly see type theory become more prominent, not less. There is some chance that programmers turn to constraint solvers or ML models for program verification instead, but if they do, mathematicians will not follow.
Type theory is already dead, it just doesn't know it yet.
Programming languages will converge after(!) natural languages have converged. Not gonna happen in our lifetime!
> I am sure the concept of number will outlive the concept of monad in terms of popularity.
It already does. I don't get your point...
> I am sure the concept of number will outlive the concept of monad in terms of popularity.
It already does. I don't get your point...
> Programming languages will converge after(!) natural languages have converged.
Interesting point. But I think you emphasise too much the surface syntax of the language. The language will be a new form of mathematics, and it will be universal, with adapters to various natural languages, of course.
Interesting point. But I think you emphasise too much the surface syntax of the language. The language will be a new form of mathematics, and it will be universal, with adapters to various natural languages, of course.
That's beyond me. I guess I prefer to look at what can happen during my life-span. :)
One example:
Any project using a transactional database will want a monad for actions that occur within a single transaction (see e.g. the Slick `DBIO` monad).
Any project using a transactional database will want a monad for actions that occur within a single transaction (see e.g. the Slick `DBIO` monad).
[deleted]
Regarding Akka situation. I am feeling Java Loom + Structured concurrency[1,2] is coming at write time. I think lot of existing project will try to shove in virtual threads in reactive solution in sub-optimal way and It may not lead to great results. Already an implementation of Loom based server is out[3]. Going by how simple code looks and how performant code is compare to reactive solution even in ALPHA release. I am going to be using it very soon.
1. https://openjdk.org/jeps/425
2. https://openjdk.org/jeps/428
3. https://medium.com/helidon/helidon-n%C3%ADma-helidon-on-virt...
1. https://openjdk.org/jeps/425
2. https://openjdk.org/jeps/428
3. https://medium.com/helidon/helidon-n%C3%ADma-helidon-on-virt...
Loom will be the next billion dollar mistake after nulls. Keep my words in mind for a decade or two...
Okay, are you going to give reason or is it more of a Thought leader style pronouncement?
Haha, I guess you are right.
The reason why it is a mistake is because it is essentially trying to solve the rpc problem once again even though it has been tried many times without success.
There just is a difference between making a synchronous call within your own OS thread vs. making such a call against anything else (the filesystem, the network, ...). Because you can assume that a synchronous call either succeeds and you can continue whatever you do. Or the whole thing crashes because e.g. the thread was killed due to some external effect or OOM error. But in that case, you have the guarantee that no more code on your thread is being run.
With Loom, it is not clear anymore if more code will be run based on your call or not, since there isn't an immediate difference between the two types of calls anymore (when looking at the code). This missing distinction is exactly what makes it easier to use but it also makes it very easy to use the "wrong default".
The reason why it is a mistake is because it is essentially trying to solve the rpc problem once again even though it has been tried many times without success.
There just is a difference between making a synchronous call within your own OS thread vs. making such a call against anything else (the filesystem, the network, ...). Because you can assume that a synchronous call either succeeds and you can continue whatever you do. Or the whole thing crashes because e.g. the thread was killed due to some external effect or OOM error. But in that case, you have the guarantee that no more code on your thread is being run.
With Loom, it is not clear anymore if more code will be run based on your call or not, since there isn't an immediate difference between the two types of calls anymore (when looking at the code). This missing distinction is exactly what makes it easier to use but it also makes it very easy to use the "wrong default".
Joe Armstrong (the creator of Erlang) said the same thing back in 2008.
> The fundamental problem with taking a remote operation and wrapping it up so that it looks like a local operation is that the failure modes of local and remote operations are completely different.
> If that's not bad enough, the performance aspects are also completely different. A local operation that takes a few microseconds, when performed through an RPC, can suddenly take milliseconds.
http://armstrongonsoftware.blogspot.com/2008/05/road-we-didn...
> The fundamental problem with taking a remote operation and wrapping it up so that it looks like a local operation is that the failure modes of local and remote operations are completely different.
> If that's not bad enough, the performance aspects are also completely different. A local operation that takes a few microseconds, when performed through an RPC, can suddenly take milliseconds.
http://armstrongonsoftware.blogspot.com/2008/05/road-we-didn...
We can go further - the very first of Peter Deutsch's Fallacies of Distributed Computing, written in 1994, is [1]:
> The network is reliable.
[1] https://www.computing.dcu.ie/~ray/teaching/CA485/notes/falla...
> The network is reliable.
[1] https://www.computing.dcu.ie/~ray/teaching/CA485/notes/falla...
Thx, always feels good to be confirmed by what someone write ~15 years ago. I think he's right.
A comment under Joe’s post points out that this has been understood at least since 1994.
> We argue that objects that interact in a distributed system need to be dealt with in ways that are intrinsically different from objects that interact in a single address space. These differences are required because distributed systems require that the programmer be aware of latency, have a different model of memory access, and take into account issues of concurrency and partial failure.
> We look at a number of distributed systems that have attempted to paper over the distinction between local and remote objects, and show that such systems fail to support basic requirements of robustness and reliability.
https://web.archive.org/web/20030310070307/http://research.s...
> We argue that objects that interact in a distributed system need to be dealt with in ways that are intrinsically different from objects that interact in a single address space. These differences are required because distributed systems require that the programmer be aware of latency, have a different model of memory access, and take into account issues of concurrency and partial failure.
> We look at a number of distributed systems that have attempted to paper over the distinction between local and remote objects, and show that such systems fail to support basic requirements of robustness and reliability.
https://web.archive.org/web/20030310070307/http://research.s...
I'll take your bet.
First of all, the difference between threads is not nearly as severe as the difference between (remote) machines. There is an analogy to be made, but that's all it is - an analogy. Most applications don't care about nitty gritty thread-management performance.
Second, people said all that shit about network calls and yet... here we live in the age of distributed computing and it keeps getting more distributed. It's rapidly getting to the point where remote boundaries are something you consider as an optimization step. Most boring old business applications are "fast enough" even though the XyzService lives on another machine.
First of all, the difference between threads is not nearly as severe as the difference between (remote) machines. There is an analogy to be made, but that's all it is - an analogy. Most applications don't care about nitty gritty thread-management performance.
Second, people said all that shit about network calls and yet... here we live in the age of distributed computing and it keeps getting more distributed. It's rapidly getting to the point where remote boundaries are something you consider as an optimization step. Most boring old business applications are "fast enough" even though the XyzService lives on another machine.
> First of all, the difference between threads is not nearly as severe as the difference between (remote) machines
The whole reason for Loom is to improve performance of code that would otherwise be blocking. So what code is blocking? Exactly: code that waits for the OS (files, network, etc.). A call from one thread to the other isn't really a blocking call and that is not really what project Loom's main focus is about - at least as far as I can tell.
The whole reason for Loom is to improve performance of code that would otherwise be blocking. So what code is blocking? Exactly: code that waits for the OS (files, network, etc.). A call from one thread to the other isn't really a blocking call and that is not really what project Loom's main focus is about - at least as far as I can tell.
I think that I disagree. Not because I think Loom is a good design, but because I've seen the same design mistake committed a couple times before, and, despite initial hype, people tend learn to hate and avoid it long, long before it can become as intractable a problem as null is.
The worst I anticipate coming from it is some hassles in production and a whole lot of time wasted futilely trying to explain why I don't like it to people who've had 1/10 as much time as me to become bitter and jaded from working in the profession.
The worst I anticipate coming from it is some hassles in production and a whole lot of time wasted futilely trying to explain why I don't like it to people who've had 1/10 as much time as me to become bitter and jaded from working in the profession.
> there isn't an immediate difference between the two types of calls anymore (when looking at the code)
There is: sync calls don't change. Async calls use the Future::fork call, all within your parent thread block scope.
There is: sync calls don't change. Async calls use the Future::fork call, all within your parent thread block scope.
Are you saying that Thread.sleep() will still be blocking its OS-thread completely so that this thread executes no other code until the end of the sleep call?
Because otherwise your claim "sync calls don't change" is wrong - since this is how it currently works.
Because otherwise your claim "sync calls don't change" is wrong - since this is how it currently works.
We are talking virtual threads here(project loom), i think, no?
https://openjdk.org/jeps/428
Basically, you don't have a thread context anymore, or you don't have a use for it anymore
https://openjdk.org/jeps/428
Basically, you don't have a thread context anymore, or you don't have a use for it anymore
> We are talking virtual threads here(project loom), i think, no?
No.
Currently, when I have code (not using futures or anything) and in the middle there is a Thread.sleep() then I know that this thread will be blocked until the sleep is over (or interrupted) and _no other code is being executed on this thread_.
So the question is: will this behaviour change? Because if it does, then Loom breaks existing code. And that's what it does. And it does it not by accident but on purpose, to retroactively improve performance of exactly those situations where OS threads are blocked.
No.
Currently, when I have code (not using futures or anything) and in the middle there is a Thread.sleep() then I know that this thread will be blocked until the sleep is over (or interrupted) and _no other code is being executed on this thread_.
So the question is: will this behaviour change? Because if it does, then Loom breaks existing code. And that's what it does. And it does it not by accident but on purpose, to retroactively improve performance of exactly those situations where OS threads are blocked.
ah ok i see your single thread is blocked nevermind
That's the very definition of what sleep() does, and the reason why, if you're calling it in an async context, you need to dispatch it in a special "blocking" dispatcher, as opposed to the other regular async calls.
That doesn't answer my question to the OP. I know what sleep() does and how to use it, but that's not the point.
Doesn't the problem you mention for Loom applies equally to OS threads? What's the difference? Loom just lets you create more threads but with OS threads you are doing IO too.
This is independent of OS threads or green threads. The problem is that with Loom the developer loses control whether they can execute something on one OS thread only or not. Whereas right now they conciously have to decide if they want to run something sync or async.
Nothing is stopping the developer from starting a single thread executor and using that to launch many virtual threads. Is that what you meant?
Well, that is something that is desired and also something we can already do in the JVM world.
What I mean is that semantics of existing code changes (and becomes harder to understand for future code).
What I mean is that semantics of existing code changes (and becomes harder to understand for future code).
Loom doesn't hide exceptions. Now you just write the exception handling the same way you would write synchronous exception handling.
It does look awfully like the async/await mess languages with bad concurrency adopted as a crutch for not having good concurrency.
Erlang/Golang model of superlight "threads" exchanging messages appears to be much better at both being actually concurrent and making most code look decent and easy to see what is actually happening.
Erlang/Golang model of superlight "threads" exchanging messages appears to be much better at both being actually concurrent and making most code look decent and easy to see what is actually happening.
> model of superlight "threads" exchanging messages
That's exactly what Loom is.
That's exactly what Loom is.
Goroutines have been very successful.
And not just goroutines. The whole Go runtime is basically what Loom aspires to be. All functions async by default and preemptible. Writing code that looks like it's blocking but is in fact async. "Await" as the default action to do with an async function, and "go" being the optional action.
So far the reception has been very good and it works very well in practice. To me it's a pain now to work with languages that don't work like that. I'd argue it's Go's biggest advantage, really.
The Zig approach looks very good as well (If I understand it correctly, the underlying functions basically get compiled to whatever the caller wants them to be. Async or not. We'll see how that pans out in practice as the language gets more traction.).
So far the reception has been very good and it works very well in practice. To me it's a pain now to work with languages that don't work like that. I'd argue it's Go's biggest advantage, really.
The Zig approach looks very good as well (If I understand it correctly, the underlying functions basically get compiled to whatever the caller wants them to be. Async or not. We'll see how that pans out in practice as the language gets more traction.).
"All functions async by default and preemptible." Really? I thought functions were sync by default unless you add the 'go' keyword.
The `go` keyword means you want to run this function concurrently to what you're doing right now.
You can think of it this way, to use terms from other languages: in Go, every function really returns a Future. But every function call has an `await` implicitly. Using the `go` keyword signals that you don't want that `await`. The call-site action doesn't change whether or not the function itself is asynchronous or not (it is).
However, if you use a mutex in Go, or wait on a channel, or try to write to a TCP connection, those calls won't block an OS thread. Additionally, if a goroutine goes on too long and others are waiting, it will be stopped and the OS thread will work on a different goroutine for a while.
You can think of it this way, to use terms from other languages: in Go, every function really returns a Future. But every function call has an `await` implicitly. Using the `go` keyword signals that you don't want that `await`. The call-site action doesn't change whether or not the function itself is asynchronous or not (it is).
However, if you use a mutex in Go, or wait on a channel, or try to write to a TCP connection, those calls won't block an OS thread. Additionally, if a goroutine goes on too long and others are waiting, it will be stopped and the OS thread will work on a different goroutine for a while.
Is this really true? My impression was that the 'go' keyword means a green thread is spun up for the function to run in and this wrapper returns immediately (hence the need for channels or waitgroups etc to get the results back). I can't imagine that every synchronous function call creates a green thread, that seems massively wasteful.
It doesn't create a green thread.
I meant async in the technical underlying runtime sense of not blocking an OS thread when doing seemingly blocking operations and tried to describe it in an approachable way. Async in the sense of a python or rust function that is declared as async. If you think in terms of function colors (async and non-async) Go only has async ones.
The `await` and `go` bit are an intuition about how Go works, where waiting for the result right away is the default, while running concurrently needs to be called for.
It of course doesn't create needless goroutines on every function call.
I meant async in the technical underlying runtime sense of not blocking an OS thread when doing seemingly blocking operations and tried to describe it in an approachable way. Async in the sense of a python or rust function that is declared as async. If you think in terms of function colors (async and non-async) Go only has async ones.
The `await` and `go` bit are an intuition about how Go works, where waiting for the result right away is the default, while running concurrently needs to be called for.
It of course doesn't create needless goroutines on every function call.
I don't see anything in the docs about cancelling a standard function. Maybe internally Go represents a function as some type of future but for all practical purposes, it looks to me like a function in Go is just as synchronous as as a function in say java.
There's a big difference. If you write to a file using the stdlib in java, you will block an OS thread. In Go you won't.
That does not mean all Go calls are cancelable, they're not.
If, in a Scala/Python/Rust async function you use a synchronous stdlib function, that call will block the whole OS thread with it.
The following experiment will show you the difference:
In Java, run 10 futures on a threadpool of 4 workers, with each future doing a thread.Sleep(1s). That will finish after 3 seconds.
In Go, run 10 goroutines with GOMAXPROCS=4, with each doing time.Sleep(1s). That will finish after 1 second.
That does not mean all Go calls are cancelable, they're not.
If, in a Scala/Python/Rust async function you use a synchronous stdlib function, that call will block the whole OS thread with it.
The following experiment will show you the difference:
In Java, run 10 futures on a threadpool of 4 workers, with each future doing a thread.Sleep(1s). That will finish after 3 seconds.
In Go, run 10 goroutines with GOMAXPROCS=4, with each doing time.Sleep(1s). That will finish after 1 second.
Yes I understand the difference between threads and fibers. That is a much different conversation than "All functions async by default and preemptible."
If you run non-async (blocking) code in a fiber, then it will block the underlying OS thread.
Functions need to be compiled in a special way and use IO in a very specific way (async io) in order for them to be properly runnable by fibers.
This specific way is commonly referred to as "async", or "nonblocking", and all functions in Go are that way, including all IO functions available in the stdlib.
Functions need to be compiled in a special way and use IO in a very specific way (async io) in order for them to be properly runnable by fibers.
This specific way is commonly referred to as "async", or "nonblocking", and all functions in Go are that way, including all IO functions available in the stdlib.
Why?
> We’re left with the Scala FP communities, which yield awesome libraries and are awesome people, but the ecosystem is essentially a microcosm of the US political landscape.
This sentence puzzles me. Does anybody know what the author could have meant with it? As a European Scala FP programmer, I have no idea.
This sentence puzzles me. Does anybody know what the author could have meant with it? As a European Scala FP programmer, I have no idea.
If you click on the "Politics" tag (which the author has attached to the article...), you'll quickly learn why.
They are a fan of free speech == unrestricted speech. Most larger ecosystems these days have a code of conduct, restricting some forms of expression if they are deemed detrimental to the community. Something that very much riles advocates of unrestricted speech. Often, having a code of conduct is conflated with social justice activism - a movement that is prominently lamented in US politics more so than Europe.
Note: I'm not interested in debating which side is right here, or if that conflating of positions makes sense. Just pointing out the likely origin of the "microcosm" comment.
They are a fan of free speech == unrestricted speech. Most larger ecosystems these days have a code of conduct, restricting some forms of expression if they are deemed detrimental to the community. Something that very much riles advocates of unrestricted speech. Often, having a code of conduct is conflated with social justice activism - a movement that is prominently lamented in US politics more so than Europe.
Note: I'm not interested in debating which side is right here, or if that conflating of positions makes sense. Just pointing out the likely origin of the "microcosm" comment.
There's a lot of players involved in the Scala OSS drama. You can read about it here: https://www.reddit.com/r/scala/comments/9a11p1/newbie_wonder...
Suffice to say there's a lot of people at each others' throats, and it probably won't get better.
Suffice to say there's a lot of people at each others' throats, and it probably won't get better.
That thread is 4 years old...I wouldn't say that's reflective of the current situation, nor do I find "probably won't get better" a great take, because the Scala OSS situation tries to not-repeat-mistakes.
Hell the worst thing the Scala Discord deals with it are spambots!
Hell the worst thing the Scala Discord deals with it are spambots!
Well, since then various factions that emerged have only come to hate each other more, a prominent "middle ground" member of the community disappeared after accusations that he was a sexual abuser, and the ecosystem seems to have firmly split between Zio and Cats, so I wouldn't exactly say things have gotten better.
> since then various factions that emerged have only come to hate each other more
There are (recent) threads out there on the interwebs were people suggest using Cats Effect or ZIO(or as a better Python) without it being hateful. And there are enough people not going at each other because of some effect library.
I am not saying everything is good, there is enough room for improvement, but I feel like you have an outdated view of the Scala ecosystem. For example "ecosystem firmly split between ZIO and Cats" doesn't ring true either, there are tools/libraries like, scala-cli and Mill or tapir coming out that offer a more pragmatic experience, without locking you down to the pure FP dogmatism.
> a prominent "middle ground" member of the community disappeared after accusations that he was a sexual abuser
Yes, this stirred up a lot of controversy and I found this indeed a failure of the Scala community, I don't think that means things haven't gotten better though.
There are (recent) threads out there on the interwebs were people suggest using Cats Effect or ZIO(or as a better Python) without it being hateful. And there are enough people not going at each other because of some effect library.
I am not saying everything is good, there is enough room for improvement, but I feel like you have an outdated view of the Scala ecosystem. For example "ecosystem firmly split between ZIO and Cats" doesn't ring true either, there are tools/libraries like, scala-cli and Mill or tapir coming out that offer a more pragmatic experience, without locking you down to the pure FP dogmatism.
> a prominent "middle ground" member of the community disappeared after accusations that he was a sexual abuser
Yes, this stirred up a lot of controversy and I found this indeed a failure of the Scala community, I don't think that means things haven't gotten better though.
Typelevel vs ZIO (John DeGoes) drama? Allegations against Jon Pretty?
tl;dr Some of the notable FP people in the Scala ecosystem associate with known white supremacists and support them. [1] When confronted, this small subset of Scala folk decided to side with supporting the white supremacists because they aren't personally negatively affected by racism as they're white themselves. This small group of prominent Scala folk bifurcated the Scala community. They then went on to gaslight others by claiming this is "free speech" (it's not) and causing conflict. The Scala community responded by adding codes of conduct to various conferences and OSS projects, which compel members to act morally.
[1] http://meta.plasm.us/posts/2020/07/25/response-to-john-de-go...
[1] http://meta.plasm.us/posts/2020/07/25/response-to-john-de-go...
This is a bunch of disingenuous, guilt-by-association, kafka-esque nonsense.
For instance, defending someone against the charge of white supremacy is clearly not the same thing as defending white supremacists.
That neither you nor the article you linked bothered to acknowledge that distinction is quite damning of your ability to think critically.
For instance, defending someone against the charge of white supremacy is clearly not the same thing as defending white supremacists.
That neither you nor the article you linked bothered to acknowledge that distinction is quite damning of your ability to think critically.
Kotlin is a fine middle ground. I would say that coroutines was a misstep (though that's a matter of taste), but otherwise their choices have been pragmatic, and their multiplatform efforts are impressive.
Yeah, the interop makes Kotlin also a hundred times easier to test out. No changes to setup or tooling, just drop a few lines in your pom.xml and you're good to go.
But curious, what's wrong with the coroutines? For some projects I've found them a nice abstraction when you have lots of IO-bound tasks, and they're bound at various places in the code making use of a single executor+threads/tasks hard to scale.
But curious, what's wrong with the coroutines? For some projects I've found them a nice abstraction when you have lots of IO-bound tasks, and they're bound at various places in the code making use of a single executor+threads/tasks hard to scale.
> But curious, what's wrong with the coroutines?
Maybe I need to revisit them, as I've only used them (on 1.6) in the context of kotlinjs (which has a limited implementation) so perhaps my impression is flawed. That said, I didn't like how viral they are in the codebase. In an executor/thread paradigm, you can box up the asynchronous behavior quite cleanly; in a codebase that uses coroutines, I ended up propagating `suspend fun` up and back in my codebase.
Maybe I need to revisit them, as I've only used them (on 1.6) in the context of kotlinjs (which has a limited implementation) so perhaps my impression is flawed. That said, I didn't like how viral they are in the codebase. In an executor/thread paradigm, you can box up the asynchronous behavior quite cleanly; in a codebase that uses coroutines, I ended up propagating `suspend fun` up and back in my codebase.
Ah, yes. The "which color is your function" is a bit problematic, but nothing inherit to Kotlin's approach I feel. I'm having the same issues in an asyncio python project now, for instance.
I drop scala into old maven projects all the time by dropping in the scala maven plugin
I disagree. Obviously, this is all just subjective preference and opinion, so parent should not take this as me saying they're wrong.
I hate Kotlin's "middle ground" approach.
Scala has persistent data structures for collections, which means that non-destructive updates and copies are cheap. This is great for an immutable-first approach. Kotlin uses Java's mutable collections, so all of the standard APIs in Kotlin make full copies. Sometimes it might even be surprising where copies are made. For example: `listOf(1, 2, 3).toList()` makes a copy of the list instead of just returning it. To understand why this is necessary, see my next point.
Scala's mutable collections are NOT sub-types of its immutable collections. In Kotlin, there is no such thing as an immutable collection interface. You have MutableList and List, but despite the confusing naming, List is NOT immutable because MutableList is a sub-type of List. So any time you write a function that takes a List parameter, you can't assume that it's not actually being mutated from another thread while your function is running. That means that you technically can't even assume a List is non-empty after you check `if (l.isNotEmpty()) { useElement(l[0]) /* this might crash */ }`.
So Kotlin's middle ground approach means that it's inefficient to use the pseudo-functional APIs and its collection types are not concurrency-safe.
Then, there's no error handling mechanism in the language. Well, there's throwing unchecked exceptions. But the Kotlin team tells you not to do that. They tell you not to do that, but that's actually the only thing that is done in the standard library, the kotlinx.libraries, and every single thing that IntelliJ actually publishes. So, it's very "do as I say" with no examples. At least in Scala we have Try, Either, and "for-comprehensions" (a.k.a. monad comprehension, do-notation, etc). Kotlin "recommends" we use sum types to express failures, but without monad comprehensions, it's extremely awkward and verbose, so I've literally never encountered a Kotlin library in the wild that does anything but throw exceptions for business logic failures. I strongly believe that it was precisely to avoid scaring off Java devs that they didn't do do-notation and monadic error handling.
I don't mind colored functions. I do absolutely HATE that Kotlin coroutines use exceptions for control flow and business logic. It's so hard to correctly handle sub-jobs in coroutines in any non-trivial case with cancellations, etc.
They also decided to not do type-classes, so we get half-baked, ad-hoc, cherry-picked type-class-like features such as extension functions and multi-receivers. I especially dislike extension functions because the receiver is resolved statically (it has to because of how it works under the hood), which is NOT the way regular method calls work, which adds yet another inconsistency to the language that's impossible to catch at compile time.
Ugh. And I'm working on Kotlin code today, so now I've got myself all upset about it. lol.
I hate Kotlin's "middle ground" approach.
Scala has persistent data structures for collections, which means that non-destructive updates and copies are cheap. This is great for an immutable-first approach. Kotlin uses Java's mutable collections, so all of the standard APIs in Kotlin make full copies. Sometimes it might even be surprising where copies are made. For example: `listOf(1, 2, 3).toList()` makes a copy of the list instead of just returning it. To understand why this is necessary, see my next point.
Scala's mutable collections are NOT sub-types of its immutable collections. In Kotlin, there is no such thing as an immutable collection interface. You have MutableList and List, but despite the confusing naming, List is NOT immutable because MutableList is a sub-type of List. So any time you write a function that takes a List parameter, you can't assume that it's not actually being mutated from another thread while your function is running. That means that you technically can't even assume a List is non-empty after you check `if (l.isNotEmpty()) { useElement(l[0]) /* this might crash */ }`.
So Kotlin's middle ground approach means that it's inefficient to use the pseudo-functional APIs and its collection types are not concurrency-safe.
Then, there's no error handling mechanism in the language. Well, there's throwing unchecked exceptions. But the Kotlin team tells you not to do that. They tell you not to do that, but that's actually the only thing that is done in the standard library, the kotlinx.libraries, and every single thing that IntelliJ actually publishes. So, it's very "do as I say" with no examples. At least in Scala we have Try, Either, and "for-comprehensions" (a.k.a. monad comprehension, do-notation, etc). Kotlin "recommends" we use sum types to express failures, but without monad comprehensions, it's extremely awkward and verbose, so I've literally never encountered a Kotlin library in the wild that does anything but throw exceptions for business logic failures. I strongly believe that it was precisely to avoid scaring off Java devs that they didn't do do-notation and monadic error handling.
I don't mind colored functions. I do absolutely HATE that Kotlin coroutines use exceptions for control flow and business logic. It's so hard to correctly handle sub-jobs in coroutines in any non-trivial case with cancellations, etc.
They also decided to not do type-classes, so we get half-baked, ad-hoc, cherry-picked type-class-like features such as extension functions and multi-receivers. I especially dislike extension functions because the receiver is resolved statically (it has to because of how it works under the hood), which is NOT the way regular method calls work, which adds yet another inconsistency to the language that's impossible to catch at compile time.
Ugh. And I'm working on Kotlin code today, so now I've got myself all upset about it. lol.
They have to be careful, there are tendencies to over-complicate things as well. I hope coroutines will die on the serve side once JVM Fibers are widely available.
Coroutines for async IO will hopefully die, but right now coroutines are the best way to implement continuations, so I hope they just become a niche feature for library authors to do things like monad comprehensions, etc. I can also imagine nice DSL-ish APIs for things like SQL transactions, where you can call "rollback()" to abort the transaction inside a closure, instead of throwing an exception and catch-swallowing it.
The irony here is that the dependency hell within pure Scala libraries has improved tremendously and is not really a problem anymore, yet we need to deal with many binary compatibility issues due to transitive Java dependencies.
Things that regularly cause issues, for instance when assembling JARs that get shipped to a Spark cluster at work: Guava, Jackson, Kryo, Log4j, Hadoop's transitive dependencies (like Netty) ... not Scala's fault.
Things that regularly cause issues, for instance when assembling JARs that get shipped to a Spark cluster at work: Guava, Jackson, Kryo, Log4j, Hadoop's transitive dependencies (like Netty) ... not Scala's fault.
> Maybe this is just me getting older (going to turn 40 soon). Maybe all programming is terrible.
Similar age and that is my experience. There are just so many roadblocks, things that don't work properly and you need to mess around debugging or googling github/stackoverflow to resolve before you can get to the fun part. I'm sure this was the same when I was younger, but I had more energy and was able to plow forward regardless.
Similar age and that is my experience. There are just so many roadblocks, things that don't work properly and you need to mess around debugging or googling github/stackoverflow to resolve before you can get to the fun part. I'm sure this was the same when I was younger, but I had more energy and was able to plow forward regardless.
Programming isn't fun anymore. Modern ecosystem is too complex for fun.
Are all of them though? Web stuff is if you fall down the hole of "everything must be a docker container" and "chase latest JS fads" but I wonder if there is a saner route. Also things like console apps should still be pretty sane, depending on what you are building.
However trendy programming has very much become pointlessly complex.
However trendy programming has very much become pointlessly complex.
I think lots of programmers (including myself) get lost in the programming language features and forget to have fun with what the application actually does.
I worked at a Scala shop, a little over 10 years ago, and it wasn't fun then, either. 1) IDE support was unstable (Eclipse was basically unusable, IntelliJ was better.) 2) Builds were slow 3) Everyone using their own little dialect, and arguments would ensue over whether we should use that feature or not.
Perhaps it's better now.
Perhaps it's better now.
It is, by quite a bit.
While the "Scala IDE" project is dead for all practical purposes, IntelliJ IDEA's Scala plugin is actually pretty amazing. There's also a VisualStudio plugin that does pretty much the same and is advancing by leaps and bounds. There are also interconnecting projects that provide i.e. language server or build server that are reused by other projects. It's pretty modular. Metals (https://scalameta.org/metals/) is amazing.
In general the language has become a wee bit faster to build, there was good progress with build times during the 2.12/2.13 cycles.
With Scala3 the language got a bit simpler; concepts that were implemented explicitly using (hehe) implicits got their own keywords and a lot of the opinionated boilercode that cause a lot of debates is now generated during complication and hidden. A lot of "standardization" has occurred.
While the "Scala IDE" project is dead for all practical purposes, IntelliJ IDEA's Scala plugin is actually pretty amazing. There's also a VisualStudio plugin that does pretty much the same and is advancing by leaps and bounds. There are also interconnecting projects that provide i.e. language server or build server that are reused by other projects. It's pretty modular. Metals (https://scalameta.org/metals/) is amazing.
In general the language has become a wee bit faster to build, there was good progress with build times during the 2.12/2.13 cycles.
With Scala3 the language got a bit simpler; concepts that were implemented explicitly using (hehe) implicits got their own keywords and a lot of the opinionated boilercode that cause a lot of debates is now generated during complication and hidden. A lot of "standardization" has occurred.
I think the IDE issue still exist in many projects due to the complexity of generic FP libraries + bad support for scala 3. The last scala project I worked on used scala3 + cats and it was very touch and go if we could continue using this stack due how flaky intellij behaved. Multiple times a day autocomplete would just stop working. This btw was noticably better in scala 2.13.
I experience 1 & 2 quite a bit, 3 a bit less but I can totally see how that would be a problem.
It is.
Having tried to use Scala only indirectly via a DSL and having given up for various build issues, I thought it was only due to my ignorance of the system.
But having said that, this paragraph jumps out as completely perplexing:
"We’re left with the Scala FP communities, which yield awesome libraries and are awesome people, but the ecosystem is essentially a microcosm of the US political landscape. I’m guessing all programming communities are turning to this nowadays. As an Eastern European, however, it kind of pisses me off."
Please don't tell me there are political camps in FP now.
But having said that, this paragraph jumps out as completely perplexing:
"We’re left with the Scala FP communities, which yield awesome libraries and are awesome people, but the ecosystem is essentially a microcosm of the US political landscape. I’m guessing all programming communities are turning to this nowadays. As an Eastern European, however, it kind of pisses me off."
Please don't tell me there are political camps in FP now.
> Please don't tell me there are political camps in FP now.
Nope. Well, politics is pervasive because politics is just the word we have to describe how people in groups interact. I'll summarize the situation:
There's a very small minority of prominent Scala people that are fine giving space and a platform in the community to people that are known white supremacists. [1] It's unfortunate that they're decided to inject their brand of politics into the Scala community. The community has had to respond by adopting codes of conduct that compel members to act with basic decency and morality.
[1] http://meta.plasm.us/posts/2020/07/25/response-to-john-de-go...
Nope. Well, politics is pervasive because politics is just the word we have to describe how people in groups interact. I'll summarize the situation:
There's a very small minority of prominent Scala people that are fine giving space and a platform in the community to people that are known white supremacists. [1] It's unfortunate that they're decided to inject their brand of politics into the Scala community. The community has had to respond by adopting codes of conduct that compel members to act with basic decency and morality.
[1] http://meta.plasm.us/posts/2020/07/25/response-to-john-de-go...
> Please don't tell me there are political camps in FP now.
All nontrivial groups of humans end up with political camps. If you don't notice it in a space, it probably means that there is one dominant political camp and it is the one you are in.
All nontrivial groups of humans end up with political camps. If you don't notice it in a space, it probably means that there is one dominant political camp and it is the one you are in.
> I’m also having affectionate memories of JavaScript and Python
I am afraid, things are equally messy in JavaScript and Python too. "X language isn't fun anymore" is exactly how I feel about X = JavaScript, X = Python, X = C++, X = Java and many other languages.
There was a time when I found Python and Js to be very fun languages. But recently the ecosystem has been becoming a mess. Build breakages on dependency upgrades are the biggest fun-killer IMHO.
Heck, there was a time when I found even Java to be fun. C++ too was fun in its early days. But every language keeps adding more syntax, more complexity and more ideas that deviate from the original design goals of these languages. These additions make the languages messy and the simple and characteristic ideas for which the languages were once loved get lost in all the complexity. I find it really disappointing. I really wish the languages preserved their original culture and philosophy.
For the never-ending and ever-increasing churn in all the languages I have gradually gone back to adopting Emacs Lisp and Common Lisp for all my personal programming needs. Common Lisp's standard is frozen in time, so for better or worse, I am protected from the constant churn I see in other languages. Emacs Lisp has a really good leadership that has been very wise to avoid adding additional complexity to the language. I wish the more modern languages were more reluctant in adding new complex ideas into the languages.
I am afraid, things are equally messy in JavaScript and Python too. "X language isn't fun anymore" is exactly how I feel about X = JavaScript, X = Python, X = C++, X = Java and many other languages.
There was a time when I found Python and Js to be very fun languages. But recently the ecosystem has been becoming a mess. Build breakages on dependency upgrades are the biggest fun-killer IMHO.
Heck, there was a time when I found even Java to be fun. C++ too was fun in its early days. But every language keeps adding more syntax, more complexity and more ideas that deviate from the original design goals of these languages. These additions make the languages messy and the simple and characteristic ideas for which the languages were once loved get lost in all the complexity. I find it really disappointing. I really wish the languages preserved their original culture and philosophy.
For the never-ending and ever-increasing churn in all the languages I have gradually gone back to adopting Emacs Lisp and Common Lisp for all my personal programming needs. Common Lisp's standard is frozen in time, so for better or worse, I am protected from the constant churn I see in other languages. Emacs Lisp has a really good leadership that has been very wise to avoid adding additional complexity to the language. I wish the more modern languages were more reluctant in adding new complex ideas into the languages.
I couldn't tell you exactly why (though I have some ideas), but Lisps seem to settle into amazingly stable languages. Even Clojure, with all its initial trendiness, has been remarkably resistant to bloat and churn. Such things as it's added have largely been either standardisations of things that people were doing anyway, or very natural extensions of ideas that were already there, and it still generally passes the "compile X year old code" test.
> I couldn't tell you exactly why (though I have some ideas), but Lisps seem to settle into amazingly stable languages. Even Clojure, with all its initial trendiness, has been remarkably resistant to bloat and churn.
I would say that the core reasons are well understood:
1) The fact that there is built-in syntactical stability in any Lisp since the code must comprise valid Lisp data structures + a couple of special symbols.
2) The second reason has to do with the fact that Lisp macros allow language extensions directly by users, provided those extensions comply with fact 1. When users can extend the programming language by adding libraries, there is little reason for the programming language designers to chase every trend in language design, ending up with the kitchen sink—sorry "multi-paradigm"—languages of today. The core stays small.
I would say that the core reasons are well understood:
1) The fact that there is built-in syntactical stability in any Lisp since the code must comprise valid Lisp data structures + a couple of special symbols.
2) The second reason has to do with the fact that Lisp macros allow language extensions directly by users, provided those extensions comply with fact 1. When users can extend the programming language by adding libraries, there is little reason for the programming language designers to chase every trend in language design, ending up with the kitchen sink—sorry "multi-paradigm"—languages of today. The core stays small.
Amusingly, point #2 brings its own set of complainers because they once had a bad experience with C macros.
> Lisps seem to settle into amazingly stable language
Lisps are built around being a simple base supporting in-language extensibility (it's the killer feature that has kept it alive as a language family, and there is lots of experience with how to do it in Lisp which means new Lisps tend to get it right from the start), which means that there is relatively little reason to break it to add features, you just build on top.
Of course, the downside of that is that it is very common for projects to have lots of code in what amounts to a project-specific DSL that is both close enough to be confused with and different enough for that confusion to be dangerous compared to how any other project does many of the same things.
Lisps are built around being a simple base supporting in-language extensibility (it's the killer feature that has kept it alive as a language family, and there is lots of experience with how to do it in Lisp which means new Lisps tend to get it right from the start), which means that there is relatively little reason to break it to add features, you just build on top.
Of course, the downside of that is that it is very common for projects to have lots of code in what amounts to a project-specific DSL that is both close enough to be confused with and different enough for that confusion to be dangerous compared to how any other project does many of the same things.
Clojure has massive amounts of ecosystem and toolchain pain, even though it is a cool language. Most common dev environment for it is a complex emacs tool chain. If you are seeking the simple joys of programming, Clojure is unlikely to be what you want.
I beg the differ. Setting up a Clojure deps environment requires like one file, want a REPL to connect to your editor? Usually add one/two lines to the deps.edn file + install the extension for your editor.
The ecosystem also has a huge emphasis on backwards compatibility and finishing libraries rather than the constant churn you see in other ecosystems. I can usually find a 5 year old Clojure library and include in my project without any problems at all, and when a major library want to try out an idea that changes the interface, they usually start a new library instead of forcing everyone to use the new interface they've come up with.
I'd say if you're seeking simplicity in terms of environment and programming, Clojure is definitely the way to go. And this is coming from someone who knew 0% Java coding before jumping into Clojure, and almost never touch/read any Java code when doing Clojure programming.
The ecosystem also has a huge emphasis on backwards compatibility and finishing libraries rather than the constant churn you see in other ecosystems. I can usually find a 5 year old Clojure library and include in my project without any problems at all, and when a major library want to try out an idea that changes the interface, they usually start a new library instead of forcing everyone to use the new interface they've come up with.
I'd say if you're seeking simplicity in terms of environment and programming, Clojure is definitely the way to go. And this is coming from someone who knew 0% Java coding before jumping into Clojure, and almost never touch/read any Java code when doing Clojure programming.
> Most common dev environment for it is a complex emacs tool chain.
IntelliJ + Cursive is not far behind. From the 2021 Clojure survey 43% of the devs were on Emacs and 31% on IntelliJ/Cursive. Then 12% VS Code etc.
Anyway I don't think an Emacs setup to develop in Clojure is that complex. I'm using Emacs with both Cider and LSP: doesn't strike me as particularly complicated to set up. If you're familiar at all with Emacs, it's pretty straightforward to configure.
If you're not familiar with Emacs, you can use IntelliJ with the Cursive plugin: apparently as much as one third of all the Clojure dev opt for that setup.
As a sidenote apparently 52% of the Clojure devs are on OS X and "only" 37% on Linux.
IntelliJ + Cursive is not far behind. From the 2021 Clojure survey 43% of the devs were on Emacs and 31% on IntelliJ/Cursive. Then 12% VS Code etc.
Anyway I don't think an Emacs setup to develop in Clojure is that complex. I'm using Emacs with both Cider and LSP: doesn't strike me as particularly complicated to set up. If you're familiar at all with Emacs, it's pretty straightforward to configure.
If you're not familiar with Emacs, you can use IntelliJ with the Cursive plugin: apparently as much as one third of all the Clojure dev opt for that setup.
As a sidenote apparently 52% of the Clojure devs are on OS X and "only" 37% on Linux.
I don't believe this assessment comes from a professional Clojurist. Emacs is common but not necessary -- you can easily reach for Calva in Visual Studio Code. Leiningen provides a tested and very accessible build environment. But I prefer the Cognitect tools deps toolchain instead, which does have a larger learning curve. Again, the developer can choose. The author and many in the comments decry JSON parsing pain in Scala. JSON is handled elegantly in Clojure -- while Jackson (neatly wrapped by Cheshire) has its occasional CVEs to wrangle, you can instead employ clojure.data.json which is performant and free of Java transitive dependency bloat and CVE surface. The transitive dependency hell mentioned in the article seems to be exacerbated by Scala tooling, though Java inter-dependencies can be complex and difficult to manage in any JVM language. I have found Clojure's tools deps toolchain to give the most elegant dependency management experience I have experienced on the JVM.
setup and emacs were quite simple for me - for emacs I just installed clojure-mode and cider via melpa like any other package. I think later I added paredit. All should include snippets for your emacs init file on their github project pages.
When you have a project source file open you can M-x `cider-jack-in` (or C-c C-x j j) to open a fresh repl right in emacs. I found this useful advice for after cider and clojure mode are installed (skip the “configuration” section) - https://www.braveclojure.com/basic-emacs/
Setup on the Clojure/filesystem/JVM side was just leiningen - install lein and then `lein new app foo` gives you a fresh project dir for `foo`. You should probably install lein before the emacs stuff as cider may need a working Clojure install, not sure.
When you have a project source file open you can M-x `cider-jack-in` (or C-c C-x j j) to open a fresh repl right in emacs. I found this useful advice for after cider and clojure mode are installed (skip the “configuration” section) - https://www.braveclojure.com/basic-emacs/
Setup on the Clojure/filesystem/JVM side was just leiningen - install lein and then `lein new app foo` gives you a fresh project dir for `foo`. You should probably install lein before the emacs stuff as cider may need a working Clojure install, not sure.
Clojure with VSCode (with the Calva extension) is a breeze.
”There are only two kinds of languages: the ones people complain about and the ones nobody uses.” - Bjarne Stroustrup
HAHAHAHHA, Stroustrup, author of quite the monstrosity, would say that wouldn't he? rofl
i feel golang and c partially, take(go sound weird in this context) a different router and we need to appreciate this type of low change languages or the python 3/2 way of change for scratch both are ways to make better software, knowing that allow ecosystems need to be re written i wish in 5 year the idea of python 4 image even when they say don't, to make a new and better langues, lua is the clear example than people want simplicity
we need to accept this change or we are hanged by the limitation of our past
There are definitely languages that people complain about but which nobody uses. Hare was a good example of this most recently.
Pretty much this. Any language worth using will have its complainers. This is generally a good thing :)
I'm in a similar-ish boat. I enjoy most languages that I learn... for a while. Once the excitement wears off, though, I start to see the flaws or inconsistencies. And, eventually, the flaws are the only things I notice anymore.
Of course, that's as much a criticism of my own attitude as it is of any particular programming language. But, in my defense, I think that we truly haven't "solved" the problem of software development. Ideally we'd need languages that make it easy to describe our human intent, make it hard to make mistakes, and are resource-efficient. There is no such language yet.
I used to also love C++ and Java. I liked the feeling of control that C++ gave me- believe it or not, I thought that writing 5 constructors for a class/struct was somehow good...
It would be hard for me to even say I have a "favorite" language today. The language I hate the least is probably Rust, but even that has its warts, weaknesses, and inconsistencies. I used to like Swift almost as much until they kept tacking on features that are nothing at all like the core of the language- now I kind of hate Swift. I enjoy Kotlin for about 30 minutes at a time until I bump into one of its many design inconsistencies or incompatible/incomplete features. I did enjoy Clojure even though I'm not a huge fan of non-static typing. It at least has a consistent vision and is clearly implemented with real engineering (like using persistent data structures and immutable-first designs, as opposed to most other languages that just tack on random pieces of "FP" and say "Who cares if you make umpteen short-lived, heap-allocated, copies of that array? Computers are fast!" Ugh...).
Of course, that's as much a criticism of my own attitude as it is of any particular programming language. But, in my defense, I think that we truly haven't "solved" the problem of software development. Ideally we'd need languages that make it easy to describe our human intent, make it hard to make mistakes, and are resource-efficient. There is no such language yet.
I used to also love C++ and Java. I liked the feeling of control that C++ gave me- believe it or not, I thought that writing 5 constructors for a class/struct was somehow good...
It would be hard for me to even say I have a "favorite" language today. The language I hate the least is probably Rust, but even that has its warts, weaknesses, and inconsistencies. I used to like Swift almost as much until they kept tacking on features that are nothing at all like the core of the language- now I kind of hate Swift. I enjoy Kotlin for about 30 minutes at a time until I bump into one of its many design inconsistencies or incompatible/incomplete features. I did enjoy Clojure even though I'm not a huge fan of non-static typing. It at least has a consistent vision and is clearly implemented with real engineering (like using persistent data structures and immutable-first designs, as opposed to most other languages that just tack on random pieces of "FP" and say "Who cares if you make umpteen short-lived, heap-allocated, copies of that array? Computers are fast!" Ugh...).
I agree with this so much. I loved Python for decades. Kinda loathe it now. All scripting languages have fallen into this, managing interpreter, test tools, and dependencies in a dev environment, CI/CD, and prod is more work than doing new stuff.
Java/Spring is obnoxious. Spring just enjoys breaking APIs or behavior on patch releases so much. Well, and I have a personal dislike of Java/C++/C# style OO. The temptation to over engineer is too great.
I’ve been enjoying Go more (I have Pascal and C roots). But I feel the pain coming as the ecosystem grows.
I haven’t LISPed in years. Maybe I’ll tinker in Clojure again. I don’t care for Emacs, and last time I checked, setting up a CL was a PITA. Sigh, even choosing a LISP/Scheme is a journey in itself.
Java/Spring is obnoxious. Spring just enjoys breaking APIs or behavior on patch releases so much. Well, and I have a personal dislike of Java/C++/C# style OO. The temptation to over engineer is too great.
I’ve been enjoying Go more (I have Pascal and C roots). But I feel the pain coming as the ecosystem grows.
I haven’t LISPed in years. Maybe I’ll tinker in Clojure again. I don’t care for Emacs, and last time I checked, setting up a CL was a PITA. Sigh, even choosing a LISP/Scheme is a journey in itself.
Clojure has massive amounts of ecosystem and toolchain pain, even though it is a cool language. Most common dev environment for it is a complex emacs tool chain. If you are seeking the simple joys of programming, Clojure is unlikely to be what you want.
This was the path i was sign posted to take and I felt like onboarding was fun:
Clojure is one of my fun languages. I laughed along to a TSoding video where the chap was quite openly dismissive of clojure as he went along but everything he tried just worked and fell into place like dominos. It just made me chuckle. https://m.youtube.com/watch?v=7fylNa2wZaU
I have Bob Nystrom’s interpreters book and i intend to use clojure as i go through that. We’ll see how successful i am…
1. I needed to install clojure https://clojure.org/guides/install_clojure
2. I needed an editor, i wanted to use VSCode so the Calva plugin was what i needed https://calva.io/paredit/
3. I needed to learn how to edit Clojure, i tried going beyond this point without learning paredit and it slowed me down so i came back and invested an evening - in vs code do ctrl+shift+p then choose the calva getting started repl
4. You need build tooling and it seemed the choices were lein (easy user experience but not “blessed” future direction? - not sure about what i’m saying here but it’s the understanding i formed). Tools.deps is the blessed approach but designed to customise the heck out of it - problematic for a beginner like me! Thankfully you can park the customisation for later and just get started with a well laid out starter https://github.com/practicalli/clojure-deps-edn - there’s even a video walks you through its features, all the inspectors and visualisers are nice to know about but not needed yet on a beginner journey
At this point I was free to do whatever. In my case so far that’s meant a toy project in reframe (loved it), another in luminus (also loved it), then i went off on learning more of the language since i felt lack of familiarity was most of my challenges with my luminus project.Clojure is one of my fun languages. I laughed along to a TSoding video where the chap was quite openly dismissive of clojure as he went along but everything he tried just worked and fell into place like dominos. It just made me chuckle. https://m.youtube.com/watch?v=7fylNa2wZaU
I have Bob Nystrom’s interpreters book and i intend to use clojure as i go through that. We’ll see how successful i am…
Thanks for preventing the frustration there. I’ll try to survey the landscape I guess.
I also haven’t taken on rust. But I’m really wanting to play with a smaller language that has enough to do something practical with. The C replacement languages like Nim are cool, but not appealing for me yet.
It’s been a while since I’ve used a LISP. I’ve always gotten things out of those forays that changed the way I looked at making software.
I also haven’t taken on rust. But I’m really wanting to play with a smaller language that has enough to do something practical with. The C replacement languages like Nim are cool, but not appealing for me yet.
It’s been a while since I’ve used a LISP. I’ve always gotten things out of those forays that changed the way I looked at making software.
> Clojure has massive amounts of ecosystem and toolchain pain
Oh come on. Why do programmers like to exaggerate things in plain English? Maybe because naming variables using words like "massive", "colossal", or "monumental" won't fly in a programming language?
There's no "massive amount of toolchain pain". Did you use Clojure last time in 2012 or something?
You can literally just install Clojure and start writing Clojure programs in your shell.
Well, if you want something personalized or project-specific, then of course you'd have to learn some stuff, that's not gonna change for any general-purpose programming language. And I don't know how you can get more general purpose than Clojure - it can run on JVM; on JavaScript platform; on .NET CLR; in Flutter; can do R and Python interop, you can write bash scripts using Babashka and nbb.
The days when you needed to learn Emacs to use Clojure are well in the past. Today you can write Clojure in Vim, VSCode, IntelliJ, Atom, Sublime, Nightcode, Emacs and even Eclipse.
Oh come on. Why do programmers like to exaggerate things in plain English? Maybe because naming variables using words like "massive", "colossal", or "monumental" won't fly in a programming language?
There's no "massive amount of toolchain pain". Did you use Clojure last time in 2012 or something?
You can literally just install Clojure and start writing Clojure programs in your shell.
Well, if you want something personalized or project-specific, then of course you'd have to learn some stuff, that's not gonna change for any general-purpose programming language. And I don't know how you can get more general purpose than Clojure - it can run on JVM; on JavaScript platform; on .NET CLR; in Flutter; can do R and Python interop, you can write bash scripts using Babashka and nbb.
The days when you needed to learn Emacs to use Clojure are well in the past. Today you can write Clojure in Vim, VSCode, IntelliJ, Atom, Sublime, Nightcode, Emacs and even Eclipse.
There's been a fair amount of churn in the ecosystem, even if the language itself has been very stable. Leiningen was ubiquitous 5-6 years ago, but if you
switched to using deps for dependency management you lost the ability to run tests or build uberjars and had to manually re-create these on a per-project
basis. Now there's tools.build, but that also requires you to manually write essentially the same tasks for basic functionality in each project. Leiningen
and tools.deps also seem to resolve depedencies differently, so you can run into issues simply by migrating from one to the other.
That's not "massive amounts of toolchain pain", this happens in every general-purpose language, I'd say: that's "business as usual".
Like in Javascript, for example, any lib composed with CRA (Create React App) is painfully difficult to re-use in non-CRA apps. You constantly run into dependency resolution pain with Haskell; Python has toolchain resolution problems; .Net has its own challenges. Well, at least .Net folks don't have to run three different, incompatible versions of Visual Studio anymore to compile a single project. I do remember those days.
If I had to run multiple versions of Clojure, Leiningen, or CIDER on a single machine to compile different projects, or if Clojure folks had to invent something like pyenv, yeah, I'd agree that there is a problem.
You just can't make everyone happy. People either complain that "Clojure is dying" because some lib hasn't been updated since March, or "Clojure has too much churn" because Cognitect rolled out a new lib.
Clojure earned the fame of being very stable because you can pick any five-six years old project and it still would compile. Now you're complaining that you've decided to switch to a different build tool and saying it's painful?
Do you know what's painful? Having to migrate from Angular to React and to keep them both in the same .js project during the transition phase. Clojure has nothing of that sort. So many times we slowly moved from one thing to another with virtually zero downtime.
I can compare the frustration you seem to describe with my own experience building thing in different languages. Clojure by far is the least frustrating in that regard.
Like in Javascript, for example, any lib composed with CRA (Create React App) is painfully difficult to re-use in non-CRA apps. You constantly run into dependency resolution pain with Haskell; Python has toolchain resolution problems; .Net has its own challenges. Well, at least .Net folks don't have to run three different, incompatible versions of Visual Studio anymore to compile a single project. I do remember those days.
If I had to run multiple versions of Clojure, Leiningen, or CIDER on a single machine to compile different projects, or if Clojure folks had to invent something like pyenv, yeah, I'd agree that there is a problem.
You just can't make everyone happy. People either complain that "Clojure is dying" because some lib hasn't been updated since March, or "Clojure has too much churn" because Cognitect rolled out a new lib.
Clojure earned the fame of being very stable because you can pick any five-six years old project and it still would compile. Now you're complaining that you've decided to switch to a different build tool and saying it's painful?
Do you know what's painful? Having to migrate from Angular to React and to keep them both in the same .js project during the transition phase. Clojure has nothing of that sort. So many times we slowly moved from one thing to another with virtually zero downtime.
I can compare the frustration you seem to describe with my own experience building thing in different languages. Clojure by far is the least frustrating in that regard.
Clojure with VSCode (with the Calva extension) is a breeze.
Python is still a lot of fun in certain areas:
- machine learning, because AI is fun, and it's very easy to play with it in python. Also because you can easily stitch services together that allow you to make cool apps without having to code the hard part, like creating a discord bot to talk to midjourney.
- anything that will use pydantic and type hints to generate parsing and validation. Fastapi, typer, etc. It's really a blast to just define types, and see your web api take off.
But it is to be expected that when something has reached a critical mass, it becomes banal, and therefore not exciting anymore.
Also, the Python ecosystem and resources have accumulated a lot of legacy stuff, and has been flooded with new comers content, so the noise to signal ratio is not great these days.
I though as a python expert I would be less relevant given the number of new devs entering the market. Boy was I wrong. It just feel like having a cheat code to ask for more money to my clients, by the sheer amount of things I learned because I was there 15 years ago.
The dependency thing is a good example. Dependencies is in actually a better state that it used to be, but because there is so much noise, very few people can enjoy it because they would have to setup python in "the right way" to do so. However, unless one invests a huge amount of time in looking up for this right way, filtering all the noise is going to be impossible. Hence most people have a broken python setup, and when they try to install something, it has a high chance of breaking.
Of course, technical dept, and our inability to pay it back as a community, doesn't help.
- machine learning, because AI is fun, and it's very easy to play with it in python. Also because you can easily stitch services together that allow you to make cool apps without having to code the hard part, like creating a discord bot to talk to midjourney.
- anything that will use pydantic and type hints to generate parsing and validation. Fastapi, typer, etc. It's really a blast to just define types, and see your web api take off.
But it is to be expected that when something has reached a critical mass, it becomes banal, and therefore not exciting anymore.
Also, the Python ecosystem and resources have accumulated a lot of legacy stuff, and has been flooded with new comers content, so the noise to signal ratio is not great these days.
I though as a python expert I would be less relevant given the number of new devs entering the market. Boy was I wrong. It just feel like having a cheat code to ask for more money to my clients, by the sheer amount of things I learned because I was there 15 years ago.
The dependency thing is a good example. Dependencies is in actually a better state that it used to be, but because there is so much noise, very few people can enjoy it because they would have to setup python in "the right way" to do so. However, unless one invests a huge amount of time in looking up for this right way, filtering all the noise is going to be impossible. Hence most people have a broken python setup, and when they try to install something, it has a high chance of breaking.
Of course, technical dept, and our inability to pay it back as a community, doesn't help.
What's the cliff notes of the right way / where's the signal in noise?
I don't write Python, but Python is like Java these days, it finds you.
I don't write Python, but Python is like Java these days, it finds you.
In short, a huge number of packaging problems come not from packaging, but from the way you install, configure and call python. Unfortunatly, everybody and their mother tell you how to do this, and you'll find 1000 articles to get you in trouble, but very few to tell you what you should actually do.
The full story is pretty long and most people don't have the time and resources to learn everything about it.
The easiest way is to follow a receipe for the least pain possible, which includes limiting yourself to a single path for bootstrapping python. Here is the one I currently recommend to my teams at the end of the comment:
https://news.ycombinator.com/item?id=32805483#32807220
It can't solve as much as knowing the whole deal, but it will remove a lot of ways to shoot yourself in the foot, and work around a lot of the legacy issues. And above all, it's easy to keep around and to apply. I noticed that anything more complicated will lead to people, so I removed a lot of things from it years after years (like -m, pipx, etc).
Of course, this will not solve the setup that are already in place, which you will likely have. I can't provide a generic way to solve that, there are too many possibilities.
Hopefully the community will eventually solve most of this by providing better default in the future, but this is an excrutiatingly slow process.
The full story is pretty long and most people don't have the time and resources to learn everything about it.
The easiest way is to follow a receipe for the least pain possible, which includes limiting yourself to a single path for bootstrapping python. Here is the one I currently recommend to my teams at the end of the comment:
https://news.ycombinator.com/item?id=32805483#32807220
It can't solve as much as knowing the whole deal, but it will remove a lot of ways to shoot yourself in the foot, and work around a lot of the legacy issues. And above all, it's easy to keep around and to apply. I noticed that anything more complicated will lead to people, so I removed a lot of things from it years after years (like -m, pipx, etc).
Of course, this will not solve the setup that are already in place, which you will likely have. I can't provide a generic way to solve that, there are too many possibilities.
Hopefully the community will eventually solve most of this by providing better default in the future, but this is an excrutiatingly slow process.
My impression is Python packaging is stuck in a local maximum, and that any attempt to move out of it will be as disruptive as 2->3. Dropping support for conda et al will only split the ecosystem, hasten the rise of Julia, and make Python packaging more acrimonious. I like your simplified approach (and take a similar approach where I can), but much of the value of Python comes from its ability to be inserted without too much fuss (assuming you'd build things from source) into an existing system. I'd suggest while wheels were a good idea at the time, they've become a parallel ecosystem and source of division.
Not at all.
As I said, most packaging problems don't come from packaging itself, but for bootstrapping. Symptoms from a terrible bootstrapping situation creep up and they come out in packaging.
Unfortunaly the solution is of the worst nature possible for a FOSS project, because not technical: it's policital. This is the kryptonite of volunteer efforts.
The community has to get organised around one way to install, configure and run python. But it's really hard to do, and requires to synchronized a lot of different group of people, efforts, and make sure everyone are on the same page.
E.G, of a single point:
To chose which version of python to run, the installer for windows provides the "py" command, anaconda provides the conda prompt, but the windows store provides a suffixed command like most unix do. Most people are not aware of those differences, and when they attempt to follow a tutorial that has been written by somebody knowing only one of those combinations, the person will fail. Either with a "command not found", a broken install, "import error", a "syntax error" or installing things for one version of python and running the other version by mistake.
This will lead the person to believe packaging is broken, while it's not. The way we install and run python is broken.
But how do you solve this problem? By engaging in a long, frustrating and thankless talk with each of the parties involved. There will be debates, people will talk about taste, diversity, backward compatibility and so on. It will be a nightmare.
The alternative would be for the core devs to come up with a single recommended setup for all plateforms, with a unified configuration, and promote that massively. This will cause another huge political problem: you now have 10000 of tutorials that are referencing one of the old ways, and you will spend the next 20 years explaining to people any previous configuration are not supported. There will be a lot of complains from devs, and pressures from companies.
Either way, you end up with a load of work, and unhappy people, which nobody wants to sign for. It would be better on the long run, but nobody wants to sacrifice themself to be hated in the end.
And that's just one single point.
You still have to solve homebrew troubles, linux distro splitting python and limiting versions, bootstrapping tooling outside of venv, solving the uncanny valley of venv, and so on.
Note that we haven't even touched packaging yet.
As I said, most packaging problems don't come from packaging itself, but for bootstrapping. Symptoms from a terrible bootstrapping situation creep up and they come out in packaging.
Unfortunaly the solution is of the worst nature possible for a FOSS project, because not technical: it's policital. This is the kryptonite of volunteer efforts.
The community has to get organised around one way to install, configure and run python. But it's really hard to do, and requires to synchronized a lot of different group of people, efforts, and make sure everyone are on the same page.
E.G, of a single point:
To chose which version of python to run, the installer for windows provides the "py" command, anaconda provides the conda prompt, but the windows store provides a suffixed command like most unix do. Most people are not aware of those differences, and when they attempt to follow a tutorial that has been written by somebody knowing only one of those combinations, the person will fail. Either with a "command not found", a broken install, "import error", a "syntax error" or installing things for one version of python and running the other version by mistake.
This will lead the person to believe packaging is broken, while it's not. The way we install and run python is broken.
But how do you solve this problem? By engaging in a long, frustrating and thankless talk with each of the parties involved. There will be debates, people will talk about taste, diversity, backward compatibility and so on. It will be a nightmare.
The alternative would be for the core devs to come up with a single recommended setup for all plateforms, with a unified configuration, and promote that massively. This will cause another huge political problem: you now have 10000 of tutorials that are referencing one of the old ways, and you will spend the next 20 years explaining to people any previous configuration are not supported. There will be a lot of complains from devs, and pressures from companies.
Either way, you end up with a load of work, and unhappy people, which nobody wants to sign for. It would be better on the long run, but nobody wants to sacrifice themself to be hated in the end.
And that's just one single point.
You still have to solve homebrew troubles, linux distro splitting python and limiting versions, bootstrapping tooling outside of venv, solving the uncanny valley of venv, and so on.
Note that we haven't even touched packaging yet.
I've really enjoyed Golang for this reason. The powers that be take a cautious approach before adding major new stuff, even when the community complains loudly about lack of important features (e.g. generics for many years until recently). Go code I've written years ago is easy to adapt to new versions and ways of doing things, even when I have to switch gears to others languages for months/years at a time. Go is predictable.
IMO the problem isn't new features, but that obsolete things are never removed from the language.
But even though a feature is removed from a next version of the language, old code still needs to work. A project must be able to contain vOld and vNext files.
Another thing I also miss is better interop between languages. Is C based interop really the best we can do?
But even though a feature is removed from a next version of the language, old code still needs to work. A project must be able to contain vOld and vNext files.
Another thing I also miss is better interop between languages. Is C based interop really the best we can do?
Even Markdown is further distorted the more time passes (and it isn't even a programming language).
How so? I only use basic markdown (e.g. for ReadMes and quick note taking), so I'm fairly ignorant.
Yes, but some 'central' agencies push for specific Markdown formats/use. E.g. Nextcloud [1] wants to use Markdown as a format, to save the output of their wysiwyg text editor. Everytime you open a Markdown file in nextcloud-text, it is 'formatted' correctly, according to the Commonmark specs, and written back, _without_ asking the user.
[1]: https://github.com/nextcloud/text/issues/593
[1]: https://github.com/nextcloud/text/issues/593
Javascript and C++ are usually pretty backwards compatible - at the very least, you can run your C++ compiler in compatibility mode for a certain standard, so I don't see any need to get caught up in the churn there.
Personally I've been using Ruby for almost 9 years and I still find it fun. Maybe that's just because I tend to agree with all of the new features they add to it.
Personally I've been using Ruby for almost 9 years and I still find it fun. Maybe that's just because I tend to agree with all of the new features they add to it.
> But there was a time when I found Python and Js to be very fun languages. But the ecosystem has been becoming a mess. Build breakages on dependency upgrades are the biggest fun-killer IMHO.
It's not the way I remember. At the beginning you got Python with the batteries - and it was awesome - but for everything else you were on your own, and sometimes it was nightmarish. There was no pip, not even setuptools. Today I can install anything I want with one command on any of the 3 major platforms. Granted, there are glitches and we're accustomed to rapid progress now, but it's easy to forget how far we got.
It's not the way I remember. At the beginning you got Python with the batteries - and it was awesome - but for everything else you were on your own, and sometimes it was nightmarish. There was no pip, not even setuptools. Today I can install anything I want with one command on any of the 3 major platforms. Granted, there are glitches and we're accustomed to rapid progress now, but it's easy to forget how far we got.
> I really wish the languages preserved their original culture and philosophy.
You mention a couple of lisps as being similar to this. I wonder if there is any more programming languages that could be considered complete? Forth? C? ASL?
You mention a couple of lisps as being similar to this. I wonder if there is any more programming languages that could be considered complete? Forth? C? ASL?
ANSI C and SML probably qualify, though I hope you don’t need utf-8
You probably won't write any useful and nontrivial piece of software in C today without using external libraries, so if you really need Unicode, you will probably use one one of Unicode libs - although basic operations like copying will work without these anyway.
Meanwhile I just get shit done with PHP and JavaScript. I guess I never have to do anything on the frontend. That’s where all the disasters are.
[deleted]
I'm doing a Play framework upgrade at work right now... and boy did the scala ecosystem not make this easy.
I'm starting to worry, I had a bet that Flex (Flash based UI component library) would be the future, then I got hyped by Ruby, then I fell in love with Scala, I'm worried about getting hyped about a technology again.
> the ecosystem is essentially a microcosm of the US political landscape
what does this mean?
what does this mean?
Difficult. I will attempt to answer this in a way that won't upset people and may be informative?
Here are two ways of looking at it:
a. People in the USA* have massive fights about things that no-else cares about, and software projects put up a statement about those. This is off-putting to everyone else.
b. The USA is ahead of the curve on some political movements, and the article is expressing conservatism/anti-conservatism/a reaction towards being expected to act according to morals that aren't majority accepted in their country yet.
To decide for each particular movement whether it's (a) the wave of the future or (b) a passing fad? Who can say? You are supposedly an autonomous moral being, so use your own judgement.
*This is true of any place and any people, but everyone else has to put up with the USA's quirks because rich influential explosives. You could substitute Twitter for the USA here. Hey, who gave Twitter all those stealth bombers?
Here are two ways of looking at it:
a. People in the USA* have massive fights about things that no-else cares about, and software projects put up a statement about those. This is off-putting to everyone else.
b. The USA is ahead of the curve on some political movements, and the article is expressing conservatism/anti-conservatism/a reaction towards being expected to act according to morals that aren't majority accepted in their country yet.
To decide for each particular movement whether it's (a) the wave of the future or (b) a passing fad? Who can say? You are supposedly an autonomous moral being, so use your own judgement.
*This is true of any place and any people, but everyone else has to put up with the USA's quirks because rich influential explosives. You could substitute Twitter for the USA here. Hey, who gave Twitter all those stealth bombers?
I think the short answer is that the US is the dominant soft global empire (which is to say this is not merely military, but also economic and cultural). What happens in Rome ripples outward into the broader realm.
But I also believe that another contributing factor is that Americans, regardless of political affiliation, often demonstrate a presumption that their own provincial squabbles, concerns, and anxieties are shared by everyone else on the planet. This is not categorically unique to Americans, but such presumption is reinforced by boorish imperial egocentrism.
And, of course, some people simply don't have the sense, consideration, and social grace to know what the appropriate time, place, and means are for expressing political convictions, and as a result, obsessively pollute all manner of social interaction with the aforementioned topics.
But I also believe that another contributing factor is that Americans, regardless of political affiliation, often demonstrate a presumption that their own provincial squabbles, concerns, and anxieties are shared by everyone else on the planet. This is not categorically unique to Americans, but such presumption is reinforced by boorish imperial egocentrism.
And, of course, some people simply don't have the sense, consideration, and social grace to know what the appropriate time, place, and means are for expressing political convictions, and as a result, obsessively pollute all manner of social interaction with the aforementioned topics.
I think this is mainly in reference to John De Goes, founder of the ZIO framework:
https://typelevel.org/blog/2019/09/05/jdg.html
https://meta.plasm.us/posts/2020/07/25/response-to-john-de-g...
https://typelevel.org/blog/2019/09/05/jdg.html
https://meta.plasm.us/posts/2020/07/25/response-to-john-de-g...
It's hard to answer meaningfully without risking starting a pointless debate in the comments or being fully honest, but I will try:
There are two FP ecosystems inside the Scala community with a very adversarial relationship towards each other. The root is that many years ago the lead developer of one of those FP communities allowed (based on community feedback) a speaker to give a technical talk. There were some people demanding that he'd be cancelled based on his right-wing views. This evolved into a full-blown conflict with serious accusations over the years about political alignment.
I am not a member of the Scala community but are interested on the language and somehow this conflict kept popping up. I agree with the author about the "US political landscape" microcosm: the conflict felt absurd and completely blown-out of proportion to me as an european.
There are two FP ecosystems inside the Scala community with a very adversarial relationship towards each other. The root is that many years ago the lead developer of one of those FP communities allowed (based on community feedback) a speaker to give a technical talk. There were some people demanding that he'd be cancelled based on his right-wing views. This evolved into a full-blown conflict with serious accusations over the years about political alignment.
I am not a member of the Scala community but are interested on the language and somehow this conflict kept popping up. I agree with the author about the "US political landscape" microcosm: the conflict felt absurd and completely blown-out of proportion to me as an european.
Note this all happened years ago and thankfully the community has very much moved on.
Travis one of the guys involved has even left Scala to do his activism work full-time.
Travis one of the guys involved has even left Scala to do his activism work full-time.
I don't think the community was allowed to move on. JdG has repeatedly behaved like an asshole and poured fuel on the fire with Typelevel people who never cared about that original LambdaConf drama and his feud with Travis. Instead of moving on, he decided to make more ennemies, to the point several library maintainers don't want to touch anything even remotely related to Zio.
That speaker wasn't just anybody with 'right-wing views', it was 'Mencius Moldbug' himself. (See, for example: https://www.unqualified-reservations.org/2013/09/technology-...)
[deleted]
I think I meant "fair-right" (that's why there was a hyphen) and wanted to avoid a more exact characterization to avoid sparking a debate around it.
constant drama.
Travis Brown (a very sociopathic and toxic, straight up unstable person) tried to cancel John A De Goes, total shitshow ensued. FYI, Travis has created scripts to auto-dox people on Twitter if he doesn't like them. Travis also left Scala ecosystem after lashing out at literally everybody including Martin Odersky
Reason: De Goes invited a speaker to his LambdaConf conference, without knowing that speaker was involved in white nationalism (US). I don't remember the exact details, but it was a huge scandal
De Goes tried to reason that all kinds of people should be included in the tech conferences irrespective of their political background. Being stubborn as he is, I don't think he ever apologised. De Goes was later booted from cats project, one of the reasons why he started Zio.
IMO De Goes is a great project leader still, and many Scala devs are moving to Zio.
Travis Brown (a very sociopathic and toxic, straight up unstable person) tried to cancel John A De Goes, total shitshow ensued. FYI, Travis has created scripts to auto-dox people on Twitter if he doesn't like them. Travis also left Scala ecosystem after lashing out at literally everybody including Martin Odersky
Reason: De Goes invited a speaker to his LambdaConf conference, without knowing that speaker was involved in white nationalism (US). I don't remember the exact details, but it was a huge scandal
De Goes tried to reason that all kinds of people should be included in the tech conferences irrespective of their political background. Being stubborn as he is, I don't think he ever apologised. De Goes was later booted from cats project, one of the reasons why he started Zio.
IMO De Goes is a great project leader still, and many Scala devs are moving to Zio.
small edit: JDG did not invite the speaker, they applied to an anonymous call for papers, once it was accepted, it was later revealed he was Moldbug. JDG, after polling other under represented speakers, decided not to rescind the invitation.
I might be misremembering but wasn't there a pro slavery angle as well?
Jesus. Yeah, I will stay with TypeScript.
The commercial entity behind the Scala language didn't do enough to make it more usable for Android developers. It has been downhill ever since.
I really wonder why every time Scala is discussed on HN, someone wants to rewrite history about some mythical synergy with the Android ecosystem. This is so bizarre.
In what world would Typesafe/Lightbend have found the money and resources to pull off even a fraction of what Jetbrains did with Kotlin? Let alone convince Google.
On the other hand I'm very happy Scala isn't tied to the Android runtime.
In what world would Typesafe/Lightbend have found the money and resources to pull off even a fraction of what Jetbrains did with Kotlin? Let alone convince Google.
On the other hand I'm very happy Scala isn't tied to the Android runtime.
> In what world would Typesafe/Lightbend have found the money and resources to pull off even a fraction of what Jetbrains did with Kotlin? Let alone convince Google.
What did Jetbrains do with Kotlin that required money and resources outside of Scala's community reach? (Also, what do you mean about convincing Google?)
I learned Scala a few years back and am working with Kotlin this year. I use Android Studio - I expected to be mind-blown with the IDE support. I wasn't. The only feature worth mentioning is the automatic conversion of pasted Java code to Kotlin, which is really trivial to implement if you have tools for working with AST of both languages and a bit of free time. Scala is handicapped here, last I checked, and only got better with version 3 rewrite, but if that's a killer feature for Kotlin, then replicating it for Scala by heaping regexes until they cover 95% of cases would also work.
I honestly don't see anything in Kotlin and the IDE that couldn't be implemented for Scala as a plugin, if there was interest in that.
What did Jetbrains do with Kotlin that required money and resources outside of Scala's community reach? (Also, what do you mean about convincing Google?)
I learned Scala a few years back and am working with Kotlin this year. I use Android Studio - I expected to be mind-blown with the IDE support. I wasn't. The only feature worth mentioning is the automatic conversion of pasted Java code to Kotlin, which is really trivial to implement if you have tools for working with AST of both languages and a bit of free time. Scala is handicapped here, last I checked, and only got better with version 3 rewrite, but if that's a killer feature for Kotlin, then replicating it for Scala by heaping regexes until they cover 95% of cases would also work.
I honestly don't see anything in Kotlin and the IDE that couldn't be implemented for Scala as a plugin, if there was interest in that.
I think you're vastly underestimating the amount of work required to support a platform like Android. How many people are directly employed by either JetBrains or Google to work on the Android + Kotlin story, vs the total number of Typesafe/Lightbend employees at its peak... which has always been burning through VC money and is financially struggling even after focusing on their core knowledge domain.
> (Also, what do you mean about convincing Google?)
Google decides what Android becomes or not. What makes you think they would have been interested in Scala in the first place? Even if someone did the integration work for free (which is an insane premise), Google likes boring languages. Plus, Scala's standard library is somewhat at odds with a fast and lean mobile runtime.
> (Also, what do you mean about convincing Google?)
Google decides what Android becomes or not. What makes you think they would have been interested in Scala in the first place? Even if someone did the integration work for free (which is an insane premise), Google likes boring languages. Plus, Scala's standard library is somewhat at odds with a fast and lean mobile runtime.
> I think you're vastly underestimating the amount of work required to support a platform like Android.
That might be so, but you're not giving me a chance to change my view. I don't know, and don't care honestly, how many people are working on what; I'm asking what did those people do, specifically, that required such an immense amount of work, and what they have to show for that effort. And of course, how many people work on developing Android itself is irrelevant - we're only talking about supporting existing compiler that targets existing implementation of a JVM in an IDE and ecosystem. Put another way: what's so impressive about Kotlin's support for Android?
> total number of Typesafe/Lightbend employees at its peak... which has always been burning through VC money and is financially struggling even after focusing on their core knowledge domain.
Maybe, then, focusing on their core knowledge domain, working for almost a decade on the "next version" of the language without care, then pulling Python-like 2/3 drama when it finally landed, was simply... a bad business decision? Maybe focusing effort on making the language more accessible to more people would have played out differently? (Just guessing.)
> Plus, Scala's standard library is somewhat at odds with a fast and lean mobile runtime.
Why? Generics and implicits are compile-time features - what's in the Scala's stdlib that is incompatible with Android APIs? What does Scala have in the stdlib that Kotlin doesn't?
That might be so, but you're not giving me a chance to change my view. I don't know, and don't care honestly, how many people are working on what; I'm asking what did those people do, specifically, that required such an immense amount of work, and what they have to show for that effort. And of course, how many people work on developing Android itself is irrelevant - we're only talking about supporting existing compiler that targets existing implementation of a JVM in an IDE and ecosystem. Put another way: what's so impressive about Kotlin's support for Android?
> total number of Typesafe/Lightbend employees at its peak... which has always been burning through VC money and is financially struggling even after focusing on their core knowledge domain.
Maybe, then, focusing on their core knowledge domain, working for almost a decade on the "next version" of the language without care, then pulling Python-like 2/3 drama when it finally landed, was simply... a bad business decision? Maybe focusing effort on making the language more accessible to more people would have played out differently? (Just guessing.)
> Plus, Scala's standard library is somewhat at odds with a fast and lean mobile runtime.
Why? Generics and implicits are compile-time features - what's in the Scala's stdlib that is incompatible with Android APIs? What does Scala have in the stdlib that Kotlin doesn't?
I'm not going to try to explain why developing and maintaining tooling takes resources.
However, a few things:
- Lightbend isn't involved in Scala 3.
- Martin Odersky has taught students for decades and knows how to make Scala more accessible. He wasn't afraid of stirring controversy with new keywords and the brace-free syntax. He also has enough industry experience and connections to realize what matters for the ecosystem in the long run. Server middleware and big data frameworks are the perfect fit for Scala on the JVM. There's no evidence for some kind of missed opportunity between Android and Scala.
- Scala's standard library is rich, heavy, focused on immutability, and not always interoperable with Java's. Kotlin's standard library is very small and heavily inlined in comparison. On a mobile platform, this matters.
However, a few things:
- Lightbend isn't involved in Scala 3.
- Martin Odersky has taught students for decades and knows how to make Scala more accessible. He wasn't afraid of stirring controversy with new keywords and the brace-free syntax. He also has enough industry experience and connections to realize what matters for the ecosystem in the long run. Server middleware and big data frameworks are the perfect fit for Scala on the JVM. There's no evidence for some kind of missed opportunity between Android and Scala.
- Scala's standard library is rich, heavy, focused on immutability, and not always interoperable with Java's. Kotlin's standard library is very small and heavily inlined in comparison. On a mobile platform, this matters.
> why developing and maintaining tooling takes resources.
Developing and maintaining anything takes resources, tooling is not special at all. Yet, you still didn't say what exactly does Kotlin do that's so resource-intensive that it's impossible to replicate for Scala for the reason of lack of resources only. Do you know Kotlin's tooling?
> Lightbend isn't involved in Scala 3.
I don't get what you mean? I mean, so what? I just opened scala-lang.org - which seems to be an official Scala web page - and the information that Scala 3.2.0 was just released is at the very top of the page. It's not like PERL and Raku. And what does it matter who is involved in what if we're talking about the tooling for the language as a whole?
> Martin Odersky has taught students for decades and knows how to make Scala more accessible.
Apparently not via investing in tooling, though? If you ask Matthias Felleisen[1], who happens to also have been teaching students for 40 years at this point, he'd tell you that tooling is important for accessibility[2].
> He wasn't afraid of stirring controversy with new keywords and the brace-free syntax.
I don't know who would, actually. I'm sorry, I don't understand this sentence, could you please explain what you mean by this?
> There's no evidence for some kind of missed opportunity between Android and Scala.
I'm sorry, but that's just you being in denial. I don't intend to dispute Martin Odersky's credentials, that's completely beside the point. The point is this: in June 2019 Scala was 28th and Kotlin was 43rd on the TIOBE Index. Now, Scala is still ahead: 33rd place vs. 34th for Kotlin. And you have to account for the fact that Kotlin is almost 7 years younger. Sorry to break it you, but that's not how a healthy language's growth looks like. Clearly, there's something wrong somewhere. My interpretation is that Scala missed many chances, and disastrously so - one of them being Android development.
It's a bummer, really. I read Odersky's book in 2005, I still have the PDF. I really liked the concept of a scalable language, expressive at all levels of complexity. I learned Scala in 2009, then brushed it off in 2017. I see Kotlin for what it is: a pragmatic knock-off of Scala and Groovy. Groovy did not, but Scala had a chance to win over millions of Android developers (in addition to thousands in data centers), but blew it. I'm not happy with that.
(The other great language that could have done better but largely blew it is of course Clojure (currently 47th), but then again, they had it way harder given the language's features)
> Scala's standard library is
> rich,
I don't have a quick way of checking, could you maybe check how many classes/(other relevant entities) are there in Java and Scala respective standard libraries? I strongly suspect Java's bigger. And even that is nothing in front of Python or VW Smalltalk.
> heavy,
Why is it heavy and in what way? Too much code generated? Too big a JAR to include?
> focused on immutability,
All default (ie. used most often in idiomatic code) collections in Kotlin are immutable; the practice of favoring val over var is identical in both languages.
> not always interoperable with Java's.
What do you mean? These are all classes compiled to the same bytecode, how could they ever not be interoperable? Do you mean that you need to convert (for example) collections before you can call methods provided by Scala/Java-specific class? That's perfectly normal and counts as interoperability, and quite a high-class one at that (I mean, try to convert BEAM's list into Python's via C extension and you'll see what "not always interoperable" means...)
> Kotlin's standard library is very small
Again, can't check it easily, but yes, I get the impression that Kotlin's stdlib is a bit smaller than Scala's. Not by much though. They're both just tiny. Well, not JS-level tiny. Probably somewhere around Scheme's R7RS or OCaml.
> and heavily inlined in comparison.
Again, Scala compiler is supposed to be "intelligent enough" to produce code faster than hand-written Java in some cases! How come such a compiler has problems inlining the code of stdlib, arguably the most optimized code of all in any language? What weird things are happening in that stdlib that the compiler has such a hard time inlining them?
> On a mobile platform, this matters.
Sure. But you just said it doesn't matter for Scala, because it's happy powering server middlewares and big data frameworks, even if it means loosing out on a lot of mindshare, contributors and all that.
[1] https://en.wikipedia.org/wiki/Matthias_Felleisen
[2] https://racket-lang.org/ and https://docs.racket-lang.org/drracket/interface-essentials.h...
Developing and maintaining anything takes resources, tooling is not special at all. Yet, you still didn't say what exactly does Kotlin do that's so resource-intensive that it's impossible to replicate for Scala for the reason of lack of resources only. Do you know Kotlin's tooling?
> Lightbend isn't involved in Scala 3.
I don't get what you mean? I mean, so what? I just opened scala-lang.org - which seems to be an official Scala web page - and the information that Scala 3.2.0 was just released is at the very top of the page. It's not like PERL and Raku. And what does it matter who is involved in what if we're talking about the tooling for the language as a whole?
> Martin Odersky has taught students for decades and knows how to make Scala more accessible.
Apparently not via investing in tooling, though? If you ask Matthias Felleisen[1], who happens to also have been teaching students for 40 years at this point, he'd tell you that tooling is important for accessibility[2].
> He wasn't afraid of stirring controversy with new keywords and the brace-free syntax.
I don't know who would, actually. I'm sorry, I don't understand this sentence, could you please explain what you mean by this?
> There's no evidence for some kind of missed opportunity between Android and Scala.
I'm sorry, but that's just you being in denial. I don't intend to dispute Martin Odersky's credentials, that's completely beside the point. The point is this: in June 2019 Scala was 28th and Kotlin was 43rd on the TIOBE Index. Now, Scala is still ahead: 33rd place vs. 34th for Kotlin. And you have to account for the fact that Kotlin is almost 7 years younger. Sorry to break it you, but that's not how a healthy language's growth looks like. Clearly, there's something wrong somewhere. My interpretation is that Scala missed many chances, and disastrously so - one of them being Android development.
It's a bummer, really. I read Odersky's book in 2005, I still have the PDF. I really liked the concept of a scalable language, expressive at all levels of complexity. I learned Scala in 2009, then brushed it off in 2017. I see Kotlin for what it is: a pragmatic knock-off of Scala and Groovy. Groovy did not, but Scala had a chance to win over millions of Android developers (in addition to thousands in data centers), but blew it. I'm not happy with that.
(The other great language that could have done better but largely blew it is of course Clojure (currently 47th), but then again, they had it way harder given the language's features)
> Scala's standard library is
> rich,
I don't have a quick way of checking, could you maybe check how many classes/(other relevant entities) are there in Java and Scala respective standard libraries? I strongly suspect Java's bigger. And even that is nothing in front of Python or VW Smalltalk.
> heavy,
Why is it heavy and in what way? Too much code generated? Too big a JAR to include?
> focused on immutability,
All default (ie. used most often in idiomatic code) collections in Kotlin are immutable; the practice of favoring val over var is identical in both languages.
> not always interoperable with Java's.
What do you mean? These are all classes compiled to the same bytecode, how could they ever not be interoperable? Do you mean that you need to convert (for example) collections before you can call methods provided by Scala/Java-specific class? That's perfectly normal and counts as interoperability, and quite a high-class one at that (I mean, try to convert BEAM's list into Python's via C extension and you'll see what "not always interoperable" means...)
> Kotlin's standard library is very small
Again, can't check it easily, but yes, I get the impression that Kotlin's stdlib is a bit smaller than Scala's. Not by much though. They're both just tiny. Well, not JS-level tiny. Probably somewhere around Scheme's R7RS or OCaml.
> and heavily inlined in comparison.
Again, Scala compiler is supposed to be "intelligent enough" to produce code faster than hand-written Java in some cases! How come such a compiler has problems inlining the code of stdlib, arguably the most optimized code of all in any language? What weird things are happening in that stdlib that the compiler has such a hard time inlining them?
> On a mobile platform, this matters.
Sure. But you just said it doesn't matter for Scala, because it's happy powering server middlewares and big data frameworks, even if it means loosing out on a lot of mindshare, contributors and all that.
[1] https://en.wikipedia.org/wiki/Matthias_Felleisen
[2] https://racket-lang.org/ and https://docs.racket-lang.org/drracket/interface-essentials.h...
> I'm sorry, but that's just you being in denial
Have fun rewriting history then. Google picked Gradle, JetBrains, Kotlin, that's just the way it is. If they had been interested in Scala on Android in any way, they'd put a couple of people behind it when it came out, or at least encouraged some 20% projects. That never happened.
And it's perfectly fine. Nobody cares about the TIOBE index. Scala faces plenty enough of challenges within its core ecosystem, nobody would gain anything from targeting the Android runtime and SDK on top of that. Exactly the same way Spring developers don't give a damn about Android.
> Apparently not via investing in tooling, though?
That's a pretty ignorant comment given the amount of work that was delivered since the creation of the Scala Center.
> What do you mean?
There's a big difference between having to convert all the common data structures between Scala and Java, or simply reusing them, like Kotlin does. Plus, Scala's idiomatic usage of Option is fundamentally incompatible with libraries taking and returning nulls everywhere. Google made Kotlin first-class without having to break the entire SDK. That's a pretty huge reason Scala never stood a chance.
Have fun rewriting history then. Google picked Gradle, JetBrains, Kotlin, that's just the way it is. If they had been interested in Scala on Android in any way, they'd put a couple of people behind it when it came out, or at least encouraged some 20% projects. That never happened.
And it's perfectly fine. Nobody cares about the TIOBE index. Scala faces plenty enough of challenges within its core ecosystem, nobody would gain anything from targeting the Android runtime and SDK on top of that. Exactly the same way Spring developers don't give a damn about Android.
> Apparently not via investing in tooling, though?
That's a pretty ignorant comment given the amount of work that was delivered since the creation of the Scala Center.
> What do you mean?
There's a big difference between having to convert all the common data structures between Scala and Java, or simply reusing them, like Kotlin does. Plus, Scala's idiomatic usage of Option is fundamentally incompatible with libraries taking and returning nulls everywhere. Google made Kotlin first-class without having to break the entire SDK. That's a pretty huge reason Scala never stood a chance.
Well, thanks for not telling me anything until the very end. I asked honest, technical questions, didn't expect not to get a single concrete answer over this many posts. Have you been a Lisp or Haskell programmer before switching to Scala? You sound like their spiritual heir...
(EDIT: Also, the ignorant comment was uncalled for. I gave you the exact dates when I was involved with Scala. I don't have the duty to stay updated on what happened afterward.)
(EDIT: Also, the ignorant comment was uncalled for. I gave you the exact dates when I was involved with Scala. I don't have the duty to stay updated on what happened afterward.)
> All default (ie. used most often in idiomatic code) collections in Kotlin are immutable
That's not true. List, for example, is a read-only interface, but given that MutableList is a subtype of List, you have no actual guarantee that some other piece of code isn't modifying a list you think is immutable.
I haven't seen this leading to trouble so far because clearly the intent is to treat collections as immutable wherever possible, and because it's a tradeoff that makes Java interop easier, but it's not the same thing as true immutable collections in Scala.
Also, your comment about interoperability makes me think you haven't actually used Kotlin. Its Java interoperability is way better than Scala's (you don't have to cast collection types, for example), for better or worse (because it also inherits some of Java's flaws).
I think that Kotlin is more pragmatic and Scala is more elegant and idealistic, and both are valid goals.
That's not true. List, for example, is a read-only interface, but given that MutableList is a subtype of List, you have no actual guarantee that some other piece of code isn't modifying a list you think is immutable.
I haven't seen this leading to trouble so far because clearly the intent is to treat collections as immutable wherever possible, and because it's a tradeoff that makes Java interop easier, but it's not the same thing as true immutable collections in Scala.
Also, your comment about interoperability makes me think you haven't actually used Kotlin. Its Java interoperability is way better than Scala's (you don't have to cast collection types, for example), for better or worse (because it also inherits some of Java's flaws).
I think that Kotlin is more pragmatic and Scala is more elegant and idealistic, and both are valid goals.
I think it's more of me not remembering how it was with Scala - it's been some 5 years since I did any Scala development.
> I think that Kotlin is more pragmatic and Scala is more elegant and idealistic, and both are valid goals.
Yes, I have the same impression.
However, I don't believe this was an initial goal of Scala. I remember reading the Scala book by Odersky in 2005 (or around that time) and my impression was that Scala was meant to be pragmatic as well. The OO+FP mix was innovative at the time (it's not anymore), but neither side was made to be dominant. That changed, with - and I'm guessing again - Haskell expats who abused implicits and the type system almost to the point of breaking to pursue their brand of "generic programming". I don't know what happened exactly and why, but when I learned Scala in 2009 it was because I didn't want to touch Java but I had to work on the JVM with lots of Java libraries. And Scala back then was ok for that purpose, like Kotlin is today. When I revisited it in 2017, it was still kind of ok for that and for me, but the community and ecosystem seemed to have drifted away from the "better Java" use case significantly.
On the other hand, Scala 2 is now anything but elegant. Scala 3 made Scala elegant again. You can see how many changes were needed to recover from more than a decade of giving in to people interested in a particular style of programming by simply skimming the Scala 3 tour.
My background is kind of unusual: most programmers my age have worked with 5-6 languages professionally and a few more as a hobby. I used 9 languages professionally and more than 20 as a hobby. Scala was one of the most interesting languages I learned. It was C++ done right and without the design-by-comitee stigma. It was meant to be expressive at all levels of complexity, from oneliners to massive systems: Scala, a scalable language. My impression is that the initial goal was to use FP idioms to make the language expressive "in the small", and OOP to make it expressive "in the large". Then some part of the community started wielding FP hammer and striking every problem with it, without even trying to use the other part of the toolbox.
I might be wrong in all of the above, I'm just guessing based on hazy memories of long ago. Still, that's my impression as someone who is interested in programming langauges in general and who was around since the beginning, although only reading up with Scala development occasionally.
Another language that suffers similar fate is OCaml. Actually, object oriented part of OCaml is a beautiful and elegant, prototype-based and (statically) structurally-typed object system. Yet no one seems to be using it. However, OCaml is better at FP than Scala. The H-M type system and inference along with polymorphic variants cover a lot more than Scala's FP can (without abusing the language features; and also of course H-M comes with downside, ie. + and +. thing). OCaml also provides real modules and higher-order modules (dubbed functors) which Scala doesn't have, and which also improve FP style to cover more of the programming "in the large" more easily.
Again, I might be totally wrong, but I think Scala was never meant to be "Haskell on the JVM". Scala 3 highlight the pragmatic, elegant side of Scala, which I think makes my assumption plausible. (I also like Haskell, Lisps, Erlang, Prolog, and another 20 languages, so I personally could live with that direction of Scala's development. Other than the compile times. But there's no way to argue that it resulted in higher adoption rate, larger community, more packages in the ecosystem, and so on. So while I'm personally still ok with Scala, my employer is not. And comments like that of your sibling poster don't help, to put it mildly - it's Smug Lisp Weenies again, just with ( replaced with { ...)
(BTW, if I'm wrong, please tell me. I'm capable of changing my mind, really.)
> I think that Kotlin is more pragmatic and Scala is more elegant and idealistic, and both are valid goals.
Yes, I have the same impression.
However, I don't believe this was an initial goal of Scala. I remember reading the Scala book by Odersky in 2005 (or around that time) and my impression was that Scala was meant to be pragmatic as well. The OO+FP mix was innovative at the time (it's not anymore), but neither side was made to be dominant. That changed, with - and I'm guessing again - Haskell expats who abused implicits and the type system almost to the point of breaking to pursue their brand of "generic programming". I don't know what happened exactly and why, but when I learned Scala in 2009 it was because I didn't want to touch Java but I had to work on the JVM with lots of Java libraries. And Scala back then was ok for that purpose, like Kotlin is today. When I revisited it in 2017, it was still kind of ok for that and for me, but the community and ecosystem seemed to have drifted away from the "better Java" use case significantly.
On the other hand, Scala 2 is now anything but elegant. Scala 3 made Scala elegant again. You can see how many changes were needed to recover from more than a decade of giving in to people interested in a particular style of programming by simply skimming the Scala 3 tour.
My background is kind of unusual: most programmers my age have worked with 5-6 languages professionally and a few more as a hobby. I used 9 languages professionally and more than 20 as a hobby. Scala was one of the most interesting languages I learned. It was C++ done right and without the design-by-comitee stigma. It was meant to be expressive at all levels of complexity, from oneliners to massive systems: Scala, a scalable language. My impression is that the initial goal was to use FP idioms to make the language expressive "in the small", and OOP to make it expressive "in the large". Then some part of the community started wielding FP hammer and striking every problem with it, without even trying to use the other part of the toolbox.
I might be wrong in all of the above, I'm just guessing based on hazy memories of long ago. Still, that's my impression as someone who is interested in programming langauges in general and who was around since the beginning, although only reading up with Scala development occasionally.
Another language that suffers similar fate is OCaml. Actually, object oriented part of OCaml is a beautiful and elegant, prototype-based and (statically) structurally-typed object system. Yet no one seems to be using it. However, OCaml is better at FP than Scala. The H-M type system and inference along with polymorphic variants cover a lot more than Scala's FP can (without abusing the language features; and also of course H-M comes with downside, ie. + and +. thing). OCaml also provides real modules and higher-order modules (dubbed functors) which Scala doesn't have, and which also improve FP style to cover more of the programming "in the large" more easily.
Again, I might be totally wrong, but I think Scala was never meant to be "Haskell on the JVM". Scala 3 highlight the pragmatic, elegant side of Scala, which I think makes my assumption plausible. (I also like Haskell, Lisps, Erlang, Prolog, and another 20 languages, so I personally could live with that direction of Scala's development. Other than the compile times. But there's no way to argue that it resulted in higher adoption rate, larger community, more packages in the ecosystem, and so on. So while I'm personally still ok with Scala, my employer is not. And comments like that of your sibling poster don't help, to put it mildly - it's Smug Lisp Weenies again, just with ( replaced with { ...)
(BTW, if I'm wrong, please tell me. I'm capable of changing my mind, really.)
JetBrains employs 70 people working on Kotlins core.
> Today, 70+ people work on the core Kotlin project team at JetBrains
https://kotlinlang.org/assets/kotlin-media-kit.pdf
Plus a bunch of Google employees working on Kotlin stuff like the new K2 compiler.
> Today, 70+ people work on the core Kotlin project team at JetBrains
https://kotlinlang.org/assets/kotlin-media-kit.pdf
Plus a bunch of Google employees working on Kotlin stuff like the new K2 compiler.
Wasn't this a somewhat common opinion 10+ years ago, when it looked increasingly C++ in its split of user bases (weird operators for one, less boilerplate Java for others)?
I mean, that's how we got languages like Ceylon, Fantom or Kotlin.
I mean, that's how we got languages like Ceylon, Fantom or Kotlin.
Scala the language is fine. Not my favorite - it’s a little conceptually big for my taste but that’s a preference thing.
Scala the ecosystem was never fun though. I can’t decide if it’s worse than JavaScript (NPM upgrade hell sucks hard).
Scala the ecosystem was never fun though. I can’t decide if it’s worse than JavaScript (NPM upgrade hell sucks hard).
When I saw the whole having to include the compiler version in dependencies I lost interest in Scala fast. I’m using it now for work, and it’s—fine—but there does seem to be a lot of fragile magic involved with it.
What does he mean by this? (Figuratively, or literally?):
”We’re left with the Scala FP communities, which yield awesome libraries and are awesome people, but the ecosystem is essentially a microcosm of the US political landscape. I’m guessing all programming communities are turning to this nowadays.”
”We’re left with the Scala FP communities, which yield awesome libraries and are awesome people, but the ecosystem is essentially a microcosm of the US political landscape. I’m guessing all programming communities are turning to this nowadays.”
They are speaking of the feud between ZIOs creator John de Goes and long-time Typelevel steering committee member Travis Brown (https://meta.plasm.us/posts/2019/09/01/jdg-and-the-fp-commun...) and split the community along those same party lines.
Some other important context is this is around peak controversy time around codes of conduct in all programming communities. Some degree of political fighting was going to happen one way or another, but it was made substantially worse by decisions made by the Lambda Conf committee at that time to allow Curtis Yarvin to speak. You can read their rationale and it's clearly well thought-out, but in hindsight it led to a much worse outcome than if they just dropped him. Subsequent conferences after 2016 and 2017 were uneventful and uncontroversial, but the shadow of those years would never go away.
It's also a very US-centric kind of political battle that I'm sure a lot of European Scala programmers feel is strange and doesn't apply to them, but has nonetheless taken their ecosystem by hostage.
It's also a very US-centric kind of political battle that I'm sure a lot of European Scala programmers feel is strange and doesn't apply to them, but has nonetheless taken their ecosystem by hostage.
>Lambda Conf committee at that time to allow Curtis Yarvin to speak.
Actually, it wasn't the "committee" that allowed it, it was a subset of speakers from under represented groups in tech (women, minorities, PoC etc whatever term you prefer) that voted to let him speak as long as he kept to his topic.
Actually, it wasn't the "committee" that allowed it, it was a subset of speakers from under represented groups in tech (women, minorities, PoC etc whatever term you prefer) that voted to let him speak as long as he kept to his topic.
Feedback was solicited, but it was not a democratic process as is documented here: https://degoes.net/articles/lambdaconf-controversy
I have no stake in the process here. As I said, it was clearly well thought-out. But the outcome is regrettable.
I have no stake in the process here. As I said, it was clearly well thought-out. But the outcome is regrettable.
I just ignore the political people and often choose the libraries they hate, having a lot of fun
I have the same question.
What does that have to do with US politics? Seems to me to be a bit of a tenuous link.
Golang has two great things going for it:
1. Emphasis on API stability.
2. Simple dependency management that generally just works.
1. Emphasis on API stability.
2. Simple dependency management that generally just works.
Go dependency management sucks hard as soon as you leave the ‶everything open source on Gihthub″.
Having to change my global git config (e.g. https://gist.github.com/dcyou/06a4f6e0a770887fbd01fa8276b945...) to cater to Go is asinine.
Having to change my global git config (e.g. https://gist.github.com/dcyou/06a4f6e0a770887fbd01fa8276b945...) to cater to Go is asinine.
I only ever did a few hobby-level projects in scala, never more than a couple thousand lines or so. There were several reasons that stopped me from wanting to go further (sbt being so unpleasant, uncertainty about the future of things with dotty, and a community I didn't want to be associated with (the worst of whom, Tony Morris, having since been kicked out, but still)).
By chance, I happened to stumble across this fringe programming language recently: https://www.unison-lang.org/
The way that it deals with dependencies seems to fix a lot of the problems that the author has mentioned.
The way that it deals with dependencies seems to fix a lot of the problems that the author has mentioned.
Unison has come up on HN quite a few times. You might want to do a search.
While there are some language features in Scala that are a bit of a buzz kill (see https://glennengstrand.info/software/coding/java/scala for more on that), the OP is mostly complaining about https://en.wikipedia.org/wiki/Dependency_hell
The Akka BSL is a big disappointment to me as well but a better name for that would be LightBend isn't fun anymore.
The Akka BSL is a big disappointment to me as well but a better name for that would be LightBend isn't fun anymore.
I wonder what this means for Gatling (the load testing tool)?
Gatling achieves it's relative low-overhead characteristics (compared to a naive approach like JMeter's) by leveraging Akka. Does this mean Akka lawyers will be coming for Gatling customers, or will they go after a slice of Gatling's pie?
Either way, hopefully someone will reproduce the Gatling functionality on the JVM using the Loom programming model. Then we can wait a few years and start the whole dance again.
I don't have a workable solution to propose. I guess I'll just quietly polish my dancing shoes and get ready for the next song.
Gatling achieves it's relative low-overhead characteristics (compared to a naive approach like JMeter's) by leveraging Akka. Does this mean Akka lawyers will be coming for Gatling customers, or will they go after a slice of Gatling's pie?
Either way, hopefully someone will reproduce the Gatling functionality on the JVM using the Loom programming model. Then we can wait a few years and start the whole dance again.
I don't have a workable solution to propose. I guess I'll just quietly polish my dancing shoes and get ready for the next song.
Now I just miss Rust when writing Scala.
[deleted]
I started looking seriously into Scala 3 without any Scala 2 exposure 6 months ago. I do not need it for any project but I wanted to see what is there. I love it.
Also, he does not mention Chisel.
Also, he does not mention Chisel.
I love Scala, now I love Rust
They are both awesome. Good reasons to love them both even though they both have their problems. :)
This guy loves sbt. For me it's one of the main reasons to use TypeScript instead of Scala.js. npm is so much better. I have been writing a lot of code in Scala.js and Scala about a decade ago, but thinking now of it, I feel only dread. Scala the language is nice enough, but the whole ecosystem around it is so stuffy.
Give Mill a try.
You need to realize the Scala ecosystem is not monolithic. Things are mostly fine if you stay within a corner, but can get complicated when you start mixing dependencies from multiple domains. I think that is true for many languages. The JVM ecosystem is rich, and that comes at a price.
You need to realize the Scala ecosystem is not monolithic. Things are mostly fine if you stay within a corner, but can get complicated when you start mixing dependencies from multiple domains. I think that is true for many languages. The JVM ecosystem is rich, and that comes at a price.
Seconded. Mill is a very versatile build tool. It mainly focuses around modeling builds as DAGs of tasks, and thus allows you to only rerun what is necessary after changes. Other tools like Bazel are built around this model too, but IMO Mill has "taste" in the way it is configured. It also gets out of your way, you can seamlessly integrate it into various shell scripts, and you don't need to make your project revolve around your build tool.
Oh, didn't hear of it, interesting.
But anyway, I am focusing on the browser these days, and a Scala.js that a) doesn't interoperate with TypeScript b) doesn't allow me to author npm packages is too much of a hassle.
But anyway, I am focusing on the browser these days, and a Scala.js that a) doesn't interoperate with TypeScript b) doesn't allow me to author npm packages is too much of a hassle.
I yearn for maven after having to use sbt the past few years.
i have similar dependency complaints about flutter. I revisited a flutter project that was <1 yr stale and it took me days to resolve all dependencies, i ended up giving up and removing many dependencies and refactoring around it.
Scala was fun when my company was small.
Later, we need to recruit more people, it became harder and harder. Each need to learn a lot before they can contribute bug fix to product. They need to learn:
Later, we need to recruit more people, it became harder and harder. Each need to learn a lot before they can contribute bug fix to product. They need to learn:
- Scala
- Akka
- very basic of sbt (if they need to change more than basic usage, they come to me for that change, as I'm the only one who learned complex sbt syntax in our team currently)
- Play framework
- Slick
But now, several years later, Akka's license change really make us to consider switch back to plain Java and Maven one part by another. For the actor model, I really like it, it can simplify Synchronization A lot, we researched Vert.X, which seems can do most of Akka (Although I haven't research whether Akka Clustering, persistent can work similar in Vert.X yet).I don't understand why do we have to listen to this boring crap.
Most of the article are complaints about dependency convergence. Convergence is completely irrelated to Scala. It happens with any JVM projects and may happen with almost any project for any platform. There are multiple ways to address it.
Regarding Akka - let it rest in peace, it was one step ahead and ten steps back. Actors have too many fundamental problems to be a good general-purpose model.
Regarding Akka - let it rest in peace, it was one step ahead and ten steps back. Actors have too many fundamental problems to be a good general-purpose model.
> I don't understand why do we have to listen to this boring crap.
You don't? You chose to read the article yourself of your own free will. At least, I hope you did.
You don't? You chose to read the article yourself of your own free will. At least, I hope you did.
This link had been heavily spammed across all the Scala communities over last week. I'm pretty tired of this "useful" discussion.
Alright, well, this is not a Scala community so I'm sorry you've seen this in your select social circle to the point of annoyance. Still, you aren't forced to read it.
5-10 years ago Scala projects were great because the best and most motivated Java developers were keen on FP and this shiny new language which could leave behind legacy code bases. Now Scala codebases are likely legacy projects themselves and the best devs have moved only golang/rust or even Java17.
Join the Java community and enjoy the robustness / the lack of headaches!
1. SBT was never fun
2. I don't believe that scala-native was a good idea in the first place, because of all the java-interop boilerplate already present. C/JVM interop design conflicts are very hard to abstract properly. It would've been nice to adopt some WASM-compatible IR instead of MLIR/LLVM lock-in.
3. WASM-first is a very viable AOT+PGO option, it also brings new opportunities for remote exec and some interesting Architectural Approaches like automagic splitting monolith into microservices on the fly by potentialy calculating communications overhead and performing basic discrete optimizations.
So, Scala is still fun, just missing a lot of business oportunitites, it's just that Odersky decided to take another spin of EU Grants acquisition by developing a new lang.
I, personally, don't think that dotty was "good enough" to roll out last year, but overall project traction and cash-flow directions don't look that promising. And I personally choose to call it EU Budget Laundering, because it's really puzzling for me how exactly 60mil Euros grants are not enough to make Dotty stable. If no-one audits than no-one cares about it, or how does laundering and embezzlement work nowadays ?...
From a lang design standpoint, there are three things which make Scala obsolete
1. No proper formal verification - although there are things like stainless (stainless.epfl.ch) and it would've been possible to adopt zero-GC alloc during codegen by adopting CoC similarly to neut (github.com/vekatze/neut)
2. No proper support for protodef and IDL's - nowadays efficient serialization (marshaling) defines software reliability, all these JSON'y/Protobuffy/Flatbuffy thingies really causing some traction, although every single one of them are not something I'd call scalable.
3. Adopting Calculus Of Constructs (CoC) and formal verification alongside bunched-separation logic (like in F-star lang and rust) should be enough to formally prove Mem consuption, amount of IO and the respective computational overheads. Basically it would've worked similarly to CAP: pick either small mem footprint and bandwidth needed - the amount of compute power and the respective latency will be calculated and formally proven.
The exact desings of separation logic for multi-threading apps is a complex subject, but I like what Azalea Raad done with Concurrent Incorrectness Separation Logic (CISL) - it's something that would've allowed rust, for instance, to drop it's boxed types for RAII and a lot of the existing sync primitives (Arc, Barrier, Condvar, PoisonErr etc).
But who am I to talk about that... I never boiled in the Sciency Kettle and Played by the Academic Tribe Rules, spending half of my life just to copy-paste generic paperworks from here and there, filling up the gaps by slaving the Kenya/Nigeria students on forced contract terms, with usual threats, IP Extortion, common worker-contractor misclassification.
Everything professory Academic-related looks so corrupt for me nowadays.
2. I don't believe that scala-native was a good idea in the first place, because of all the java-interop boilerplate already present. C/JVM interop design conflicts are very hard to abstract properly. It would've been nice to adopt some WASM-compatible IR instead of MLIR/LLVM lock-in.
3. WASM-first is a very viable AOT+PGO option, it also brings new opportunities for remote exec and some interesting Architectural Approaches like automagic splitting monolith into microservices on the fly by potentialy calculating communications overhead and performing basic discrete optimizations.
So, Scala is still fun, just missing a lot of business oportunitites, it's just that Odersky decided to take another spin of EU Grants acquisition by developing a new lang.
I, personally, don't think that dotty was "good enough" to roll out last year, but overall project traction and cash-flow directions don't look that promising. And I personally choose to call it EU Budget Laundering, because it's really puzzling for me how exactly 60mil Euros grants are not enough to make Dotty stable. If no-one audits than no-one cares about it, or how does laundering and embezzlement work nowadays ?...
From a lang design standpoint, there are three things which make Scala obsolete
1. No proper formal verification - although there are things like stainless (stainless.epfl.ch) and it would've been possible to adopt zero-GC alloc during codegen by adopting CoC similarly to neut (github.com/vekatze/neut)
2. No proper support for protodef and IDL's - nowadays efficient serialization (marshaling) defines software reliability, all these JSON'y/Protobuffy/Flatbuffy thingies really causing some traction, although every single one of them are not something I'd call scalable.
3. Adopting Calculus Of Constructs (CoC) and formal verification alongside bunched-separation logic (like in F-star lang and rust) should be enough to formally prove Mem consuption, amount of IO and the respective computational overheads. Basically it would've worked similarly to CAP: pick either small mem footprint and bandwidth needed - the amount of compute power and the respective latency will be calculated and formally proven.
The exact desings of separation logic for multi-threading apps is a complex subject, but I like what Azalea Raad done with Concurrent Incorrectness Separation Logic (CISL) - it's something that would've allowed rust, for instance, to drop it's boxed types for RAII and a lot of the existing sync primitives (Arc, Barrier, Condvar, PoisonErr etc).
But who am I to talk about that... I never boiled in the Sciency Kettle and Played by the Academic Tribe Rules, spending half of my life just to copy-paste generic paperworks from here and there, filling up the gaps by slaving the Kenya/Nigeria students on forced contract terms, with usual threats, IP Extortion, common worker-contractor misclassification.
Everything professory Academic-related looks so corrupt for me nowadays.
Same exact problem existed before scala. I also agree it's not fun.
good riddance. the only use case for scala is spark and i'm starting to switch to the JavaRDD. Scala should have never entered the enterprise space.
Anyone thinking about porting Play to another framework?
Anyone thinking about porting Play to another framework?
Sound more like issues with sbt, I use Gradle when I write Scala, but I admit I use Kotlin nowadays.
It literally has nothing to do with sbt. Gradle won't save you from binary compatibility conflicts caused by diamond dependencies.
I can't help but notice that the majority of the libraries he mentions are Java-first.
I don't have an extremely strong argument that this is the root of many of his problem with version mismatches, but I do have a strong hunch that it is.
I've spent a little bit of time with Scala, a little bit with Clojure, and a lot with Kotlin. My biggest conclusion from all these years of working with non-Java JVM languages is that Java interop is actually a language mistake. Or, rather, Java interop ends up being "design debt". It's great to bootstrap your new JVM language into popularity because people can try to gradually switch from Java or use mature Java libraries when your $NEW_LANG ecosystem is still nascent. But, the problem is that Java libraries are written in Java style and are written within the constraints of Java and Java's type system.
The most obvious (albeit likely the least problematic) example is null in Kotlin and Scala. Both languages have superior ways to handle the "bottom type" to Java, but a Java library obviously doesn't get to use those.
The other problems come from how much information can be expressed at compile time. The biggest design flaw in Java as a language is that it combines type-erased generics and runtime type reflection/inspection. Either one of those is fine, but they are quite literally incompatible concepts. You can't apply type-based logic on a type that doesn't exist.
Yet, because of how unexpressive Java's type system is, any sufficiently complex Java library/framework will make ubiquitous use of type reflection. Usually while leveraging annotations.
I can't tell you how many type bugs I've found in the JacksonXML Kotlin compatibility module and in Vert.x with Kotlin. Nulls sneaking in where they aren't supposed to, value classes randomly causing issues because something boxes up a Function object and then uses reflection somewhere surprising, things not serializing correctly because JacksonXML or Gson doesn't understand some perfectly valid type I've defined, etc.
But something like JacksonXML should never exist in Scala. Scala has type-classes, so you can define your serialization and deserialization logic on the type itself. Then it can be checked at compile time. For Java, defining and passing around a separate serialization object for each type would be too cumbersome, so all of the serialization libraries use reflection and just hope they can figure out the deserialization at runtime. When you find out that it can't because your app crashed, then you can backtrack and "teach" Jackson/Gson how to deserialize your troublesome type with a custom deserializer class and an annotation.
And it's not just the type systems being incompatible. It's also the style and idioms. Java frameworks really like to be "magical" and hands-off, because it's so verbose to define and pass around separate classes for everything.
I believe this is also manifested in the OP's issues with libraries depending on other libraries and causing version conflicts. If Java libraries were less "plug and play", they would ask the user to provide logic, instead of saying "Don't worry, I'll do everything for you under the hood."
Is this just a cliché Java flame comment? Maybe it is. But it's based on my many years of dealing with Java and every popular JVM language (excepting Groovy; I don't have any experience with it outside of gradle).
I now have a policy that if I'm working on a Clojure, Kotlin, or Scala project, Java dependencies are nearly forbidden. It's a very high bar to include a Java library dependency, and if it uses generics or reflection, it's basically an instant "no".
I don't have an extremely strong argument that this is the root of many of his problem with version mismatches, but I do have a strong hunch that it is.
I've spent a little bit of time with Scala, a little bit with Clojure, and a lot with Kotlin. My biggest conclusion from all these years of working with non-Java JVM languages is that Java interop is actually a language mistake. Or, rather, Java interop ends up being "design debt". It's great to bootstrap your new JVM language into popularity because people can try to gradually switch from Java or use mature Java libraries when your $NEW_LANG ecosystem is still nascent. But, the problem is that Java libraries are written in Java style and are written within the constraints of Java and Java's type system.
The most obvious (albeit likely the least problematic) example is null in Kotlin and Scala. Both languages have superior ways to handle the "bottom type" to Java, but a Java library obviously doesn't get to use those.
The other problems come from how much information can be expressed at compile time. The biggest design flaw in Java as a language is that it combines type-erased generics and runtime type reflection/inspection. Either one of those is fine, but they are quite literally incompatible concepts. You can't apply type-based logic on a type that doesn't exist.
Yet, because of how unexpressive Java's type system is, any sufficiently complex Java library/framework will make ubiquitous use of type reflection. Usually while leveraging annotations.
I can't tell you how many type bugs I've found in the JacksonXML Kotlin compatibility module and in Vert.x with Kotlin. Nulls sneaking in where they aren't supposed to, value classes randomly causing issues because something boxes up a Function object and then uses reflection somewhere surprising, things not serializing correctly because JacksonXML or Gson doesn't understand some perfectly valid type I've defined, etc.
But something like JacksonXML should never exist in Scala. Scala has type-classes, so you can define your serialization and deserialization logic on the type itself. Then it can be checked at compile time. For Java, defining and passing around a separate serialization object for each type would be too cumbersome, so all of the serialization libraries use reflection and just hope they can figure out the deserialization at runtime. When you find out that it can't because your app crashed, then you can backtrack and "teach" Jackson/Gson how to deserialize your troublesome type with a custom deserializer class and an annotation.
And it's not just the type systems being incompatible. It's also the style and idioms. Java frameworks really like to be "magical" and hands-off, because it's so verbose to define and pass around separate classes for everything.
I believe this is also manifested in the OP's issues with libraries depending on other libraries and causing version conflicts. If Java libraries were less "plug and play", they would ask the user to provide logic, instead of saying "Don't worry, I'll do everything for you under the hood."
Is this just a cliché Java flame comment? Maybe it is. But it's based on my many years of dealing with Java and every popular JVM language (excepting Groovy; I don't have any experience with it outside of gradle).
I now have a policy that if I'm working on a Clojure, Kotlin, or Scala project, Java dependencies are nearly forbidden. It's a very high bar to include a Java library dependency, and if it uses generics or reflection, it's basically an instant "no".
It was always an ugly pairing of Java and worst of functional programming imo
Was it ever? To me it always seemed like a Java with the added burden of functional programming and more complicated OO.
It took some adjustment but I love it now. Not sure I could go back to Java.
If you want your engineers to spend time playing with highly academic libraries that are unnecessarily complex for the business problem you are trying to solve, choose Scala.
Although there are some complex libraries available for Scala, there's also a lot of very simple stuff.
It's a very expressive language, and sure that lets some libraries do some very powerful and complex things or find new abstractions that'll come across as really complex.
But it's also very good for expressing things simply. Earlier this year, I wrote some materials for teaching git in a little interactive OER I've been trying to build up. With Scala, I could write a little git simulation and embed it into my slides and it did not seem like a big undertaking.
Across these and the decks after it, there's quite a lot from simulating git, to visualising diff a simple diff algorithm, to doing git graphs that'll sit well in an interactive slide https://theintelligentbook.com/supercollaborative/#/decks/vc... https://theintelligentbook.com/supercollaborative/#/decks/vc... https://theintelligentbook.com/supercollaborative/#/decks/vc...
to letting students do an in-browser tutorial that tries to simulate a VS Code-like environment https://theintelligentbook.com/supercollaborative/#/challeng...
In the JS or TypeScript ecosystem, I think I'd have been hanging off so many libraries that I'd be dreading how fast my dependencies move. Here, I've got a dependency on one JS text editing widget and one JS Markdown parser, and one Scala dependency on (my own) little front-end framework ... and that's about it. The rest I could "just write".
Ok, my code ain't fantastically commented because I'm not expecting collaborators, but there's 15 commits in writing the whole darn thing, including the slide decks and interactive tutorial. https://github.com/theIntelligentBook/supercollaborative/com...
It's a very expressive language, and sure that lets some libraries do some very powerful and complex things or find new abstractions that'll come across as really complex.
But it's also very good for expressing things simply. Earlier this year, I wrote some materials for teaching git in a little interactive OER I've been trying to build up. With Scala, I could write a little git simulation and embed it into my slides and it did not seem like a big undertaking.
Across these and the decks after it, there's quite a lot from simulating git, to visualising diff a simple diff algorithm, to doing git graphs that'll sit well in an interactive slide https://theintelligentbook.com/supercollaborative/#/decks/vc... https://theintelligentbook.com/supercollaborative/#/decks/vc... https://theintelligentbook.com/supercollaborative/#/decks/vc...
to letting students do an in-browser tutorial that tries to simulate a VS Code-like environment https://theintelligentbook.com/supercollaborative/#/challeng...
In the JS or TypeScript ecosystem, I think I'd have been hanging off so many libraries that I'd be dreading how fast my dependencies move. Here, I've got a dependency on one JS text editing widget and one JS Markdown parser, and one Scala dependency on (my own) little front-end framework ... and that's about it. The rest I could "just write".
Ok, my code ain't fantastically commented because I'm not expecting collaborators, but there's 15 commits in writing the whole darn thing, including the slide decks and interactive tutorial. https://github.com/theIntelligentBook/supercollaborative/com...
Highly academic libraries, because of course companies like Comcast or Disney Streaming are universities.
Red herring.
Or just have a culture of shipping projects without futzing. We have dozens of Scala services and many dozens of engineers and this hasn’t been a problem.
> but the ecosystem is essentially a microcosm of the US political landscape. I’m guessing all programming communities are turning to this nowadays. As an Eastern European, however, it kind of pisses me off.
Yikes! It's unbelievably exhausting to hear white folk say that they don't want to deal with the consequences of European colonialism.
Racism exists. You can either be anti-racist or pro-racist. There's no middle ground when everyone lives in a society that is built on the backs of hundreds of years of stolen labor in inhumane conditions. There's not _one part_ of modern, global society that isn't affected by racism.
Remember, it's an extreme privilege to look at a part _real life for the majority of people on the planet_ and say "it's just politics."
Yikes! It's unbelievably exhausting to hear white folk say that they don't want to deal with the consequences of European colonialism.
Racism exists. You can either be anti-racist or pro-racist. There's no middle ground when everyone lives in a society that is built on the backs of hundreds of years of stolen labor in inhumane conditions. There's not _one part_ of modern, global society that isn't affected by racism.
Remember, it's an extreme privilege to look at a part _real life for the majority of people on the planet_ and say "it's just politics."
Uh,is he white? did he even mention race?
The fact you just immediately went rage mode before asking questions just proves his point.
The fact you just immediately went rage mode before asking questions just proves his point.
He did mention race by referring to the "politics" in Scala, because this refers to a specific event. You can learn about it here [1]. I presumed that this was common knowledge because it is widely known in the Scala community: perhaps I assumed too much.
And yes, he's white. You can verify this for yourself by looking at the blogpost author 's About page, a video from a talk they did [2], and with their self-identification as eastern european.
I'm unsure if you meant to do this, but your comment comes off as gaslighting: you don't know what's going on and you asserted something that is false as true. Next time, if you're not certain about what's going on, I encourage you to do a little bit of Googling.
[1] http://meta.plasm.us/posts/2020/07/25/response-to-john-de-go...
[2] https://slideslive.com/38908144/a-tale-of-two-monix-stream
And yes, he's white. You can verify this for yourself by looking at the blogpost author 's About page, a video from a talk they did [2], and with their self-identification as eastern european.
I'm unsure if you meant to do this, but your comment comes off as gaslighting: you don't know what's going on and you asserted something that is false as true. Next time, if you're not certain about what's going on, I encourage you to do a little bit of Googling.
[1] http://meta.plasm.us/posts/2020/07/25/response-to-john-de-go...
[2] https://slideslive.com/38908144/a-tale-of-two-monix-stream
First, I sincerely wish you happiness. There is no 'winning' to be had when we treat people as enemies. I don't know you, but I witnessed your behavior here. My reaction was to your behavior, not to you as a person.
> I'm unsure if you meant to do this, but your comment comes off as gaslighting: you don't know what's going on and you asserted something that is false as true
No, I didn't make any assertion. I asked questions based on your attack on the author. You comment was completely out of context of the article, so it seemed off-base. I can understand if you have inside knowledge, but your reaction was still not a good look to the majority of people like myself who are not.
> Next time... ...I encourage you to do a little bit of Googling.
Your behavior is still illustrating some of the author's point. Some individual/group cultures are cesspools of unhappy/combative people. As someone who has no desire to 'pick a side' of a language community battle, I identified with the author's lack of enthusiasm for a particular community, without knowing all the details. There's nothing wrong with that.
> I'm unsure if you meant to do this, but your comment comes off as gaslighting: you don't know what's going on and you asserted something that is false as true
No, I didn't make any assertion. I asked questions based on your attack on the author. You comment was completely out of context of the article, so it seemed off-base. I can understand if you have inside knowledge, but your reaction was still not a good look to the majority of people like myself who are not.
> Next time... ...I encourage you to do a little bit of Googling.
Your behavior is still illustrating some of the author's point. Some individual/group cultures are cesspools of unhappy/combative people. As someone who has no desire to 'pick a side' of a language community battle, I identified with the author's lack of enthusiasm for a particular community, without knowing all the details. There's nothing wrong with that.
It's almost crazy to me that such a fundamental and widely used project would switch to such a restrictive license.
Some more details here: https://coralogix.com/blog/akka-license-change/
> Lightbend are operating on a “per core” model, with their base license starting at $1995 per core (defined as a thread or vCPU)
> The license is only enforced if your company earns over $25 million in annual revenue
I guess Lightbend is really struggling, but this is probably the end of Akka outside of niche markets / large enterprises.
edit: HN discussion - https://news.ycombinator.com/item?id=32746807