Kotlin becomes second most popular language on the JVM
snyk.io
snyk.io
Recently had to go back to an older Android codebase, and immediately decided I had to start converting.
The amount of boilerplate is unbelievable. I'm able to cut the number of lines by half while increasing readability. Type/null safety is a huge added bonus
P.S. Kotlin extensions are the best
Jetpack Composer is the latest example of such, finally is ConstraintLayout and the GUI editor gettting usable, they reboot the whole thing ('cause Flutter) without even having an idea how to support ConstraintLayout and MotionLayout with Jetpack Composer based UI tooling.
Anyway, nowadays you wouldn't see me making the same statements anymore.
My first issue appeared when I was maintaining an Android app written in Java. I needed an library for some functionality. The only maintained ones were kotlin-libs. But interoperability, right? I didn't hesitated to include it. There is no way to use or extend functionality with typealiases in your java code.
IntelliJ can compile Kotlin into Java and it is easily accessible. But there is no adb debugger for kotlin.
Null Safety is just overhead imho. I know when it is appropriate or neccessary to check for null, otherwise i can get rid of it. And its more easily grep-pable the Java way.
Writing Kotlin is not so fluent as one would guess, the tooling only fools you, that it is. You can easily make use of actions like typing pfi (extends to public final int) for java aswell. But when your property changes from nullsafe to nullable, you need to rewrtiging eeevverything.
Additionally, i do not like the implicit type on member property declarations used by almost anybody. The benefit of typing less boilerplate becomes annoying when reading sources outside your ide.
Boilerplate in my opinion is code i need to write by myself. When it is generated by any IDE, i do not bother about it. We are so familiar with Java that we can abstract this boilerplate when reading sources.
Spelling Kotlin to somebody via telephone is also strange for me.
I stopped promoting Kotlin as a Java killer. Code style is too different between different developers.
And why are we creating the same libraries once again?
Anyone who thinks they can do better than a compiler for code safety is probably very new to this profession.
But there are times where you can be sure that the nullable object is not null. You got the double-exclamation-point (!!) for this. But some calls to Android-facilities doesnt accept this, so the IDE notifies you about an var, which could have changed at this point in time. Resulting in multiple !! in the same scope of function.
Same with vars, they are still needed every now and then but most of a clean codebase is hopefully vals and immutable data classes.
Isn't the fact that you have to be explicit about null the main feature of explicit null safety?
I don't have a hard stance on that, but I can see where he's coming from. My day job is all Java, and while we do occasionally have to deal with NPEs, they're just NPEs, not segfaults or things that can take down the whole program. They get caught and logged in a thread while the rest of the (server) app marches on. Programmatically, using Optional to signal intention of null as meaningful (and it is sometimes useful to have null as a meaningful "don't know" value, see http://john.freml.in/billion-dollar-mistake) works well and isn't syntactically laborious. (Additionally Optional chaining with maps is much nicer than the old way of nested if-not-null checks, but sure a "?." operator or similar would be slightly nicer.)
Common Lisp complects nil and false and the empty list '(), which originally annoyed me quite a bit, but after working with it more I see it as deeply pragmatic and it simplifies a lot of code while also making many types of annoying errors in other null-supporting languages either not relevant or much more trivial to fix. Additionally its OOP system has a function-call syntax of (method obj arg) instead of something like obj.method(arg) so in error logs you'll see "no applicable method for the generic function #method when called with arguments (nil arg)" (and in development you have the excellent condition system to resolve this without unwinding the stack and losing state, including the choice to define a method that explicitly handles a null object). But I don't see the programming language fashions moving any closer in that direction...
Without null safety that could be quite tricky, especially when combined with type inference. The value could be stored and used only later, for instance. The compiler flagging where those fields are used without a null check is convenient, it tells you exactly where to insert new code to handle the missing data.
Anyway, you are absolutely right and I am glad @jach posted an link (above) regarding my intuition (@shoutout). When I learned programming (with Java, 3 yrs. ago) my mentor pointed out that i included too null-checks, even though i was familiar with the entire code base. Just after reading a post on this platform I realized his real intention: Sometimes (most often!) we needlessy check for null. Since then, forcing me to check anytime for null feels wrong and kotlin is forcing me to do so.
Eventually I just wanted to mention downsizes which comes into my way when using kotlin daily..
Thankfully..!
I found that despite Java's plainness ... it's robust and I don't worry about 'how fast I can express myself' I'm more concerned about readability and Java is still ok there.
> I'm able to cut the number of lines by half while increasing readability.
What I've seen from kotlin code on the web is that sometimes code is so terse that it's too hard to understand, but it's probably because of not being accustomed to kotlin yet (I've written so convoluted erlang list comprehensions that I'm still ashamed, but those can squeeze 10 lines of java into one erlang line).
The goal (and the opportunity) is to make your code very declarative.
view.removeSelf()
vs. ViewGroup parent = (ViewGroup) view.getParent();
parent.removeChild(view);
Extension Properties and data classes further help centralize the contents of a class. removeSelf(view)
Not that bad, but then it doesn't sell Kotlin.If the library is open source, you can of course try to contribute changes, but they may or may not be accepted, and maybe the library is in such wide use that they don't want to break backward compatibility.
In any language it is possible to fix broken libraries.
Because the impression I get is that Kotlin is a strict improvement along every dimension. But as an outsider, I'm not sure if I"m just being blinded by hype.
* No checked exceptions destroying lambda expressions and leading to architecture problems (since exceptions are oft not used like the inventors of checked exceptions assumed).
* Functions are real first class citizens and don't need artificial interfaces.
* Named parameters with default arguments are very practical.
* `name: Type` is a better fit for type inference than `Type name`.
* Null-safety helps to avoid lots of bugs.
* The type system with `Any` as a unified root and `Unit` instead of the special case `void` makes programming with generics much easier.
* Constructors are always lean, not only for data classes (record in Java 14).
* Most things are expressions, so you can write `val a = if(cond) 1 else 99`.
* Extension functions and operator functions can be used to write simple to use and elegant APIs.
So at least for me Kotlin is definitive the better Java and I wouldn't start a new project with Java, if I could use Kotlin instead.* No checked exceptions destroying lambda expressions and leading to architecture problems (since exceptions are oft not used like the inventors of checked exceptions assumed).
* Functions are real first class citizens and don't need artificial interfaces.
* Named parameters with default arguments are very practical.
* `name: Type` is a better fit for type inference than `Type name`.
* Null-safety helps to avoid lots of bugs.
* The type system with `Any` as a unified root and `Unit` instead of the special case `void` makes programming with generics much easier.
* Constructors are always lean, not only for data classes (record in Java 14).
* Most things are expressions, so you can write `val a = if(cond) 1 else 99`.
* Extension functions and operator functions can be used to write simple to use and elegant APIs.
I personally wouldn't go for anything but Java (on JVM, that is) for anything that isn't a pet project.
Another huge advantage Kotlin has over Scala is tooling, which is basically all thanks to an IDE company creating the language. Tooling will never fall behind because they are in the business of selling tools.
As far as JetBrains, I am big fan, I have a license for R# that I gladly pay for, but JetBrains is just one company whose core set of products are rapidly being encroached upon by free alternatives.
Jetbrains is even lagging behind, look at vscode remote capabilities which is way ahead jetbrains remote features.
Best of all, I can use Java in any Java IDE.
Needs additional configuration for what the others do out of the box, like Javadoc tooltips.
Requires ten finger shortcuts.
It is also the only Java IDE unable to do mixed language debugging, Java/C/C++.
This has been true for almost two decades now - Eclipse first shipped in 2001, and it competes directly against IntelliJ, which was JetBrains' main product at the time.
And yet, they're still around.
Not sure I'd agree with this. Kotlin's ties to JetBrains means that you're basically hosed if you don't use IntelliJ. Scala's tooling works pretty much everywhere (LSP/Metals, ENSIME, IntelliJ, Eclipse/Scala-IDE).
Scala's tooling also pretty much sucks everywhere (interestingly the least sucking IDE for Scala is guess what ... Intellij!)
The parts where IntelliJ has always fallen down on Scala seem to be precisely the parts that are missing from Kotlin. I can't help feeling that the JetBrains team just "doesn't get" higher-kinded types at all. Which is a shame, because there is a lot of good stuff in Kotlin otherwise.
In your opinion.
Personally I almost get depressed when I have to switch from Emacs+Metals to Android Studio for Kotlin stuff.
[1] https://medium.com/@fommil/hide-your-real-name-in-open-sourc...
(You could say the same thing about Sun/Oracle...risks all around.)
It's being maintained. A new version (3 iirc) is about to come out. But it's not a hot bed of innovation.
I think Kotlin now already has a lot more mindshare and corporate interest behind it than Groovy ever did.
Those of us that are part of the Java world since the early days, have been through this multiple times.
Just like C on UNIX, JavaScript on the browser, ....
The hype curve is definitely in the past, but Groovy is living on quite well as a small but viable option in the plateau of productivity. In some ways that is more important because while in the hype phase it is really hard to judge the true value of a technology. The true value emerges when the hype is over.
The problem is, there isn't really a better scripting option for the JVM. While in theory lots of JVM languages (JRuby, Jython ... etc) could fill that gap, they all have ugly impedance mismatches which Groovy doesn't, so companies continue to deploy it as a scripting and DSL implementation still. I tried to substitute Kotlin for a bit and went back to Groovy because Kotlin still lacks standard scripting constructs such map and list literals etc.
Right, history repeats itself all the time ... until it doesn't. 10 years ago is not now, Kotlin is not Groovy ...
As for Valhalla, it remains to be seen how it's usable from Java, let alone anything else. But Kotlin already has a form of value type (inline classes) so perhaps it'll be an extension of that.
One cannot just change their semantics after the fact.
case class Foo(x: Int) extends AnyVal {
def square: Int = x * x
}
val bar: Foo = Foo(5)
println(bar.square) // => 25
Compiles down to (the moral equivalent of) object Foo {
def square(x: Int): Int = x * x
}
val bar: Int = 5
println(Foo.square(bar)) // => 25
If the inner value (x, in this case) can be stack-allocated or stored in registers then `Foo(x): Foo` will as well. `Foo(x): Bar` (where Bar is a supertype of Foo) will be autoboxed, but that also applies to primitive types (`5: Any` becomes a java.lang.Integer in memory). inline class { ... ]
Which is guaranteed to be always stack-allocated or stored in registers, again you cannot retrofit semantics, specially when passing those classes to binary libraries.There is also precedence for this, Scala 2.12 changed the encoding of lambdas from anonymous classes to Java 8's invokedynamic.
If you’re already familiar with OO languages and their standard coding patterns, then there’s little reason to use Java over it.
To clarify, for the Kotlin / Java users out there that might not get what I mean: the syntax for classes and constructors and default constructors and all can be very confusing when reading Kotlin compared to C#, Java or Python, since the constructor and the class declaration are halfway merged.
Please, distinguish what Scala has over kotlin separately than what cats/scalaz has over arrow. You will be surprised to see how little the list is.
Real immutable collections (might be available in a third-party library for Kotlin, but not used in the standard library or any of the ecosystem)
Well-behaved option/maybe type (arrow implements one, but it's not used in the standard library)
Either type used in the standard library where it makes sense (arrow implements one)
First-class (monadic) comprehensions in which the language behaves as normal (arrow makes an impressive effort, but it has rough edges from not being part of the language, and its implementation inherently relies on capturing pieces of imperative execution, so you can't rely on it for monads that do control flow e.g. a backtracking/nondeterminism monad).
Practical way to implement typeclasses for third-party types, that will be understood correctly by the whole ecosystem (IDEs/debuggers/etc.) Together with the above this means you can enable comprehensions for any standard library or third-party type for which they make sense, not just libraries that were built on top of arrow (e.g. standard collections, third-party database libraries, types from the Java or Android standard libraries). Arrow's annotation processing is a poor substitute for being able to do this in a first-class way, and even if it were built in, the typeclasses are a lot more cumbersome at the point of use.
Practical way to write tiny, composable functions that rely on HKT/typeclasses. In Kotlin if you want to write a one-liner you still have to cart the typeclass instance around, which might seem trivial but is actually a huge barrier to working in high functional style, where you'd write hundreds of tiny combinators that each do one simple but really generic thing.
Monad implementation for the standard way of representing presence/absence, the standard way of representing async, etc. Even with annotation processing, it's impossible to ever implement a monad instance for Kotlin's nullable types (because they're not well-behaved).
Iteratees or equivalent - a way to represent possibly-async transformation pipelines such that even the middle of a pipeline can be a well-behaved, reusable value that we can use a lot of general-purpose functions on.
Record types (relying on Shapeless) and a way to convert back and forth between case/data classes and a generic representation of them - fulfills a similar use case to "compile-time reflection". This really unlocks a lot of functional power when you combine it with applicative / monadic traversals of those generic representations - it lets you walk an object graph, doing something effectful at each node, in a completely safe, managed way.
Recursion-schemes style traversals - representing different kinds of recursion as composable values. This makes it a lot more practical to do things like tree transformations in a safe way, because it becomes ok to have 20 subtly different types of tree representing different intermediate stages of your operation.
Kind polymorphism (relies on kind-projector in Scala which has similar limitations to Arrow) - makes the above a lot more effective, as you can write functions that do the right things for generic and non-generic trees (for example).
The first half of this is more a matter of degree than of kind, because an ecosystem is more than a language. An imaginary Kotlin ecosystem in which everyone used immutable collections and everyone used arrow optionals instead of nullable types might approach the usability of Scala on this front. But the Kotlin ecosystem that actually exists does not operate this way - and, crucially, there's no way to interoperate between working this way and not. Scala was able to overcome this barrier by having implicit conversions and good typeclasses, so even if you have to use a third-party library that doesn't follow functional conventions, you can still enable functional operations for it. Kotlin can't do that; extension methods don't allow the types they're attached to to implement interfaces, so the only way to treat a third-party type as having some functional support is to plumb a typeclass instance for it around manually as arrow does.
And beyond that, trivial inconveniences matter. It's possible to write a well-behaved Either type in C++, but no-one uses them because it imposes so much code overhead that it's not worth it. Ultimately Greenspun's law applies - you can implement any language in any other one - but at the point where you're working in what's effectively a Scala interpreter written in Kotlin (which Arrow is halfway to being), you're gaining very little of Kotlin's benefits (in terms of tooling, ecosystem and so on).
And the things in the second half are more fundamental. Arrow is an impressive effort in working around the limitations of not having HKT, but it can only go so far; at some point you need real HKT in your language. (It's the same story in Scala one level higher - the things you can do with kind-projector are really impressive, but they're also no substitute for using a language with real kind polymorphism). And if you want to actually unlock the power of functional programming, it has to be practical to avoid using anything that breaks the rules of the language - reflection, bytecode manipulation, annotation processing, macros - and for that you need an equivalent of Shapeless (or Frunk in Rust), or ideally a proper record system.
I'd love to be optimistic about Kotlin - there's a lot that it cleans up - and certainly I hope that the language will eventually adopt HKT. But even then, the ad-hoc approaches of the language's early design will always be a millstone around its neck. I mean, fundamentally, Kotlin collections are mutable and nullable types are ill-behaved, and I can't see the ecosystem/culture ever managing to go through a wholesale conversion to using immutability and proper optionals (contrast this with Scala where mutable collections and null exist but you'll never see them in a mainstream Scala library). And that alone is always going to make it less pleasant to work with than Scala.
Outside of Android I wouldn't choose Kotlin.
Lambdas can't handle checked exceptions, which are the most common exceptions in the system.
There is no way to extend Stream with your own methods.
Still 8 primitive types to wrestle with.
Just to name a few issues. And there are lots and lots more.
The language is simply not extensible enough to write anything elegantly.
() -> {
try {
// do work
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
I also agree with Goetz that extension functions aren't something we need.Regarding extension methods, while they are nice, with import static it just a matter where the extended type comes, big deal.
And from experience in .NET world, hunting them down isn't always fun, even if they are just Ctrl+F12 away.
You can do exactly the same thing that Kotlin would do for you and just rethrow them as runtime exceptions. It's one extra wrapper call; not great, but not a huge overhead either.
> There is no way to extend Stream with your own methods.
That's just syntax sugar; all it's actually doing is calling a static method, which you can still do in Java.
> Still 8 primitive types to wrestle with.
You can just ignore them and use the object versions everywhere, and then it's not a problem.
There are a bunch of irritating warts in Java, but irritating warts alone are not worth switching language over.
i kinda get how this is safer, but clients can just call optionalRef.get() without checking, and boom there goes the safety. compiler warnings be damned.
You could also do this in Kotlin and boom there goes the safety:
fn nonNull(): String {
val s: String? = null
return !!s
}For back-end service/API type things in an enterprise setting, Kotlin is a good value proposition. There's also probably some truth to the idea that one reason modern Java is adding these things is because of Kotlin's existence.
Some features like named parameters or null checking might probably never make it to Java.
There is a nice talk about this that compares Kotlin to what will be in Java 19:
Really, I don't get this claim Kotlin will lack Java features. Most big Java upgrades these days are at the VM level. Kotlin gets those mostly for free, once they choose to upgrade to newer bytecode features (which they are slow at doing admittedly, but that's because they're in the middle of a compiler rewrite).
It also means that Kotlin on Android cannot just consume any random Java library, only those that are compatible with Android Java flavour of the month.
https://dev.to/martinhaeusler/why-i-stopped-using-coroutines...
https://dev.to/domnikl/kotlin-coroutines-and-javafx-threads-...
https://blog.danlew.net/2020/01/28/coroutines-and-java-synch...
Scala also is a different beast (the one I prefer personally). I can understand people not choosing Scala if they're not into FP and are afraid to be unable to recruit Scala developers.
But Kotlin being some sort of "improved Java", the philosophy stays the same, Java developers can seamlessly switch to Kotlin... The benefit of picking Java over Kotlin is pretty slim.
There are good, explainable reasons why people hate Java and Javascript. Fundamentally, one can argue that they are very nice and solid languages and all those complains aren't warranted. On the other hand if you look at them differently and treat them as low-level, sorta "assembly" languages for their respective platforms, then probably you would find out that Clojure is an amazing tool, because it can perfectly be hosted on both of them.
And given all the good design decisions that went into Clojure, one might argue that it's almost always better to choose Clojure instead of Java.
Anyway, nowadays you wouldn't see me making the same statements anymore.
My first issue appeared when I was maintaining an Android app written in Java. I needed an library for some functionality. The only maintained ones were kotlin-libs. But interoperability, right? I didn't hesitated to include it. There is no way to use or extend functionality with typealiases in your java code.
IntelliJ can compile Kotlin into Java and it is easily accessible. But there is no adb debugger for kotlin.
Null Safety is just overhead imho. I know when it is appropriate or neccessary to check for null, otherwise i can get rid of it. And its more easily grep-pable the Java way.
Writing Kotlin is not so fluent as one would guess, the tooling only fools you, that it is. You can easily make use of actions like typing pfi (extends to public final int) for java aswell. But when your property changes from nullsafe to nullable, you need to rewrtiging eeevverything.
Additionally, i do not like the implicit type on member property declarations used by almost anybody. The benefit of typing less boilerplate becomes annoying when reading sources outside your ide.
Boilerplate in my opinion is code i need to write by myself. When it is generated by any IDE, i do not bother about it. We are so familiar with Java that we can abstract this boilerplate when reading sources.
Spelling Kotlin to somebody via telephone is also strange for me.
I stopped promoting Kotlin as a Java killer. Code style is too different between different developers.
And why are we creating the same libraries once again?
Not having null safety seems like overhead to me.
> I know when it is appropriate or neccessary to check for null, otherwise i can get rid of it.
How do you know? Do you have the entire code base in your head. What about when someone new works on the project?
> And its more easily grep-pable the Java way.
What does this mean?
That said, Kotlin is awesome language with awesome tooling. I don't think that it'll go anywhere since Google declared it as a preferred Android language. So you won't make a wrong choice, it's just a matter of personal preferences. I'm more of old guy who's not afraid of writing XML and repetitive code and don't like all that modern functional one-liners.
If you mean getting in the way of writing reliable software.
There are still resources available for Kotlin + Android development but non Android resources are very few.
The plus side is because of the First Class Support in Intellij Idea for Kotlin, I can always take Java snippets and have the IDE convert them to Kotlin.
Within ~2 years, native things will hopefully become sufficient, but the state now isn't gloom and doom.
So now for every problem we need to consider Java + Guest Language idiomatic libraries + alternative build tools + alternative IDE, across the whole corporation.
Ofcourse I am banking on resources improving with time.
IMHO, any language features rank incredibly low on the list of reasons you might use a language. Things like how long has the language been popular, how long will the language be popular? How strong is the community around the language, how long will it stay strong? What else can you use the language for? What tools are available, is the tooling in a competitive market? Which of those things is most important to your application?
A lot of those questions can't be answered directly, and have to be guessed at. But in the Kotlin vs Java scenario, the choice is pretty obvious for most applications.
I think the Typescript/Javascript comparison is more apt, and at this point I'm pretty sure that Typescript will win.
There's this misconception that Kotlin is an Android only thing or a JVM only thing. The reality in both Android and server side frameworks is that the big frameworks are all moving towards being Kotlin friendly/ready. Additionally, Kotlin is rapidly moving towards being a proper full stack language with a native compiler (currently in beta), a javascript transpiler, and lots of other tooling maturing. People are already doing cross IOS/Android libraries in Kotlin.
A big advantage of Kotlin over e.g. Scala and other JVM languages that are not Java is that it is designed from the ground up make the transition as seamless as possible. Scala is so far removed from Java that it's generally a completely separate ecosystem with its own libraries, tools, frameworks, idioms, etc. Yes you can use Java stuff but it's generally frowned upon by Scala people.
This is not the case with Kotlin at all. The Android ecosystem started transitioning to Kotlin long before Google recommended that and before Kotlin 1.0 because the pain of having to deal with Java 6/7 just made that development so much better. A few years ago they started endorsing and recommending it and at this point they are clearly deprecating a lot of stuff that they did for Java that can be done better with Kotlin e.g. embracing co-routines over rxjava, adding extension functions and kotlin dsls and designing new features that really only make sense if you use Kotlin. On Android, if you are doing Java, you are working on a legacy code base.
On the server side the same is happening with e.g, Spring, which is basically the dominant server side framework for the JVM. I used Kotlin with Spring Boot 1.x/Spring 4.x, and it was a nice upgrade despite the lack of Kotlin support for it.
With Spring 5 and Spring Boot 2.x they started adding a lot of Kotlin extension functions, co-routine support (which generally makes using their reactive stuff less painful), and there's an experimental project for Kotlin DSL (https://github.com/spring-projects-experimental/spring-fu) to replace the mess of annotations that is currently needed and which reduces the need for reflection, proxies, and other tricks that currently make using Spring with Graal vm hard. Basically, what that means is that if you use Spring in a new project and you are not using Kotlin, you are probably making a mistake because you are missing out on a lot of good stuff. They'll likely not deprecate Java entirely for a long time just because there are a lot of very conservative projects in e.g. banks using Java but if you read between the lines they are basically saying Kotlin is it going forward.
IMHO, the Java language is definitely improving but just not at a pace where it actually keeps up and a lot of the stuff they add is a big compromise compared to what you get in Kotlin. and of course Kotlin is improving as well and a lot of the Java changes (and related JVM changes) also benefit Kotlin.
> This is not the case with Kotlin at all. The Android ecosystem started transitioning to Kotlin long before Google recommended that and before Kotlin 1.0 because the pain of having to deal with Java 6/7 just made that development so much better. A few years ago they started endorsing and recommending it and at this point they are clearly deprecating a lot of stuff that they did for Java that can be done better with Kotlin e.g. embracing co-routines over rxjava, adding extension functions and kotlin dsls and designing new features that really only make sense if you use Kotlin. On Android, if you are doing Java, you are working on a legacy code base.
There's a contradiction between your paragraphs; my experience is that as Kotlin projects mature, they also reach a point where developers frown on Java idioms. I mean fundamentally either the language is different from Java or it isn't; if it is, the transition isn't going to be seamless, and if it isn't, then why use it? The Kotlin community may have been better at being supportive, but the practical experience of making the transition is exactly the same (e.g. I used Spring for my early Scala projects, and found that to be a very nice way of working).
The only ones I can think of are where the language provides a feature that automates some Java boilerplate, so it wouldn't make sense to write things out by hand anymore. Otherwise they're semantically identical languages so the gap isn't big.
IMO there's a contradiction at the heart of Kotlin's positioning. As the quote goes, a language that doesn't affect the way you think about programming, is not worth knowing. If programming Kotlin is just like programming Java, why not just keep programming Java? If you want to switch to Kotlin because it's going to unlock a better way of programming, then that's going to have to mean changing how you program. It may work as a trick to get users on board at the start, but ultimately the language will have to find its own idioms and patterns, or else go the way of CoffeeScript.
Kotlin is being developed primarily by developers based in Russia. Putin relies on geopolitical conflict for consent manufacturing within the country. One of his future antics could turn into a real crisis, where Russia ends up sanctioned and isolated as a result, after a series of tit-for-tat moves, with the corresponding disruption to normal business processes.
Being a Russian product it also carries a risk of one day receiving an update with a payload from Russian secret services, if they find your firm sufficiently interesting. But it's a general consideration with software/hardware from "adversary" countries like China or Russia. The story with Huawei is the same.
But you know, the most aggressive country by far at backdooring systems is the USA. For the vast majority of us who are neither American nor Russian it's all swings and roundabouts.
The interests of all of these parties are different and that's what sometimes causes tensions, but these tensions do also exist in other programming languages that aim at a broad audience. Just look at Rust. Languages that do not show these tensions are languages owned by only one party (most of the time, a company) and that are the only stewards of the project and those controlling the agenda. The good thing about Scala is that it's flexible and it allows you to use it for your use case regardless of whether the language designers want to support your use case or not.
Your claim about Scala tooling being outdated or outright abandoned is not true. There has never been as good tooling as Scala has today, with a lot of innovation happening in the field. The reality is that Scala has really good tooling, on par with that of Kotlin and Java, and sometimes even better. Just look at projects such as Metals, Scalafix, Ammonite, mill, bloop or Scala Steward to get an idea of what I'm talking about.
Also, the Scala team is not working on Scala 3, Martin Odersky's team at EPFL --LAMP-- is. The Scala team at Lightbend is working on keeping improving Scala 2 and making sure tooling is still as good as it gets for when Scala 3 is finally released.
There are lots of people in the Scala community that are not so much into "FP language theory" or category theory and just see its potential as a cross-platform language to prototype and write robust software.
It's always tempting to agree to language X being flexible to suit everyone's needs but I would agree with John A. De Goes on that it should be either functional rather than something in the middle. Being flexible is only good on the surface, once it comes to actual daily work like reading other people's code expressiveness quickly becomes a burden.
>Your claim about Scala tooling being outdated or outright abandoned is not true.
I might have been trapped in my own little domain of data science guy and I don't know about other cool active libraries but whenever I dig something useful, it appears to be some PhD project left-overs or "last commit 5 years go" case. It's frustrating and doesn't encourage you to proceed working with the language.
So, if I ask, how does Scala future look like now that we have Java keeping up the pace with Kotlin basically sweeping the JVM newcomers and even Clojure looking good? I go read the Scala 3 goals and struggle to feel the same excitement over intersection types, better implicits, union types, type lambdas, DOT calculus of all things and all this at the cost of "Scala 3 won't be binary compatible with Scala 2" :) I am sorry but doesn't it look like a neck breaking academic crusade into oblivion? I think it does but time will tell of course.
I don't think the same thing, and other people developing the Scala language don't either, so it's a respectable opinion but tells you very little about what Scala is and will become. Scala 3 is catering for the Pythonistas and there are lots of important fixes that make the language easy to use for them.
The reality is there are lots of languages that are flexible. The important part is where they are flexible. In Java, you can do pretty much anything you want at runtime. Same with Ruby or Python. You can actually do pretty complicated stuff that screws up local reasoning about the code.
Scala is flexible at compile-time by having an expressive language. Some of this expressiveness has been sacrificed in Scala 3 to make the language simpler. But the foundational stuff stays there and time will tell how successful this release will be.
On your comments of Scala 3 and Scala 2 being binary incompatible, maybe you have missed all along that there will be no binary breaking compatibility with TASTY and the goal is that you will be able to mix Scala 2 and Scala 3 code within the same codebase.
> I might have been trapped in my own little domain of data science guy and I don't know about other cool active libraries but whenever I dig something useful, it appears to be some PhD project left-overs or "last commit 5 years go" case.
Again, check out the tooling projects I've mentioned before. Many of them don't either exist in other languages. I don't know what you're referring to with some PhD tooling project. I've been in the business of doing OSS tooling for Scala and working on the compiler toolchain for a long time. If your definition of "useful" tooling includes projects such as LMS, which was a research project, then there clearly is a mismatch between what good and useful tooling is for you and for me.
This is not true at all, Scala 2 is officially abandoned with the entire team now focused on Dotty [1]:
> we have decided that, rather than developing Scala 2.14, our efforts should go to Scala 3 instead.
[1] https://www.scala-lang.org/2019/12/18/road-to-scala-3.html
Also leaning toward FP is not theoretical zealotery, FP really helps to create more robust software (no null, better error handling, better concurrency).
(by the Scala.js maintainer Li Haoyi)
With Kotlin you get like 80 % of the good things from Scala for 20 % the efforts.
I've switched from Scala to Kotlin 3 years ago and didn't miss much (real pattern matching come to mind).
Of course it is still much smaller than Java, but Clojure can also be hosted on JS, BEAM or .Net. There's even a way to interop with Python and R.
Clojure is one of the nicest [production-ready] languages out there. It's pretty cool what it has achieved, with pretty much zero marketing effort and without support from big companies.
Scala suffers due to bad tooling. As somebody else said.
I'd still urge people to try out scala as a much better typescript (scala.js) for web
It'd be good if the OP elaborates on what "bad tooling" we have in the Scala community given that today Scala's tooling is good and on par with that of Kotlin and Java.
It would be a bit hard for Clojure to achieve that level of support.
They are trying to be the next Borland with Kotlin as their Turbo Pascal (#KotlinEverywhere), and got Google Android's team as the language godfather.
Most of GraalVM improvements regarding Scala have been thanks to Twitter.
Because what I heard is that Google pay JetBrains nothing. They forked IntelliJ Community Edition to make Android Studio and have their own development team, which honestly sounds much more like Google to me.
OTOH Google at least doesn't try to kill them outright, just to assimilate them and headhunt their employees, but Microsoft would be happy if they disappeared instantly as many of their clients have an unwanted dependency on Resharper.
VSCode just filled the void they left wide open. But I suspect Sublime and Atom are the main victims of VSCode.
I'm not saying that having more mainstream tooling wouldn't be good, but people should not be discouraged from Clojure or Lisp development because of an apparent lack of tooling.
And that's probably the only book that recommends setting up Emacs. It was published in 2015. Back then maybe the argument about tooling made sense, but honestly, have you looked around lately?
Every major editor today can be set up for Clojure programming.
Even most popular (and oldest) languages can't brag about being equally supported in all major editors, and Clojure can.
I evaluated Ceylon vs Kotlin in 2015, back when Kotlin wasn't even close to a 1.0 release and neither had any adoption. They're very similar in a lot of ways and so the choice came down to a lot of small things added up rather than any one big thing. I chose Kotlin for a lot of reasons, but a few (in no particular order) were:
1. It had a more convenient syntax. The Ceylon designer felt that autocomplete meant verbose syntax didn't matter but it does. "variable Integer foo = 10" isn't just a typing issue but also a reading issue. "var foo = 10" is better.
2. Ceylon deviated more from the JVM ecosystem than Kotlin, in particular, it invented its own collections like Scala, but which didn't appear to be much different to regular Java collections. This means idiomatic Ceylon would obviously be a Ceylon library to users and not a Java library. Kotlin uses standard Java collections but enhanced via extension methods. It also provides a bunch of knobs to make the output classes seem like idiomatic Java classes in the few places that doesn't happen automatically, so you can reasonably use it for libraries. This makes a huge difference to Java interop. Kotlin is really the only JVM language that takes Java interop seriously: the rest all treat it as a price of admission to use the JVM at all and minimise their effort on it.
3. Ceylon was mostly tooled for Eclipse which, in my view, is an inferior IDE to IntelliJ. The tooling was itself not as good as even the pre-1.0 Kotlin plugin.
4. Ceylon had invested heavily in a complicated module and type system, which was the primary set of things they emphasised. These sorts of features have a relatively poor track record of delivering value; slightly-stronger-than-Java seems to be about the sweet spot at the moment. Much stronger than that and you end up in Haskell. Kotlin went in for more type inference and more usable generics (convenience), Ceylon
5. Ceylon seemed much riskier to me (correctly). Nothing used it. It was clearly the project of one guy at Red Hat who'd had a previous successful project (Hibernate), but Red Hat weren't talking about it or using it in any way. On the other hand JetBrains had a large team assigned to Kotlin and were explicit that they were creating it to use in IntelliJ itself. The existence of a Java to Kotlin converter tool showed that they were completely serious about this, as J2K was a lot of work to build and would only be useful in a truly serious assault on existing Java codebases. Ceylon seemed far more interested in fancy type systems than the practical details of adoption.
6. Ceylon had some weird gotchas and interop glitches that weren't normal for Java-like languages, like a sensitivity to the case of the first letter of identifiers (I know Go does this too) and difficulty handling Java arrays. There are named constructors (cool) which don't compile to static methods as is idiomatic for Java but some weird Ceylon specific notation (boo). This sort of thing showed it wasn't trying to be "just a better Java" which is what I was in the market for.
I think the language is quirky in a lot of ways with the verbose syntax being one of them. I liked some aspects of the type system that made it look close to an ML flavor, although the language had heavy OOP syntax. In this way I thought it was similar to Scala.
There are a few nice write ups from the author on the process of coming up with the syntax. The one talking about constructors is a good example [1].
However don't party too much, all of them counted together are still a minority versus Java on JVM, as clearly shown.
[0] Binary incompatibilities, very very slow compilation speed, atrocious build tool
Is anyone using Kotlin to write services, what are your experiences with that ?
Seriously, I have great hopes for Kotlin. It corrects some Java's most egregious sophomore mistakes, it doesn't try (and fail) to be Haskell like Scala did, it's accessible AND has a major company behind it. Kotlin is surely something I wish I could use at work.
I agree that switching between languages can kind of drain you of a good touch to your working language. I think this is a real downside about all the other langugaes that a dev today has to deal with too (Ansible, bash, CloudFormation, CSS, etc. I like Clojure because you can use the same good language on the frontend and backend.
> 3) Recruitment for Kotlin devs is impossible. You have to train people and companies won't do that, so there's no pool of talent ready to go.
Is this really a common problem in the corporate world? In my experience people are to quick to pick up at least dynamic languages. I guess it's possible that Clojure is easier in this respect, or maybe Clojure jobs just attract people with a more exploratory attitude.
Don't get me wrong, I appreciate both Groovy, Scala as well as Kotlin. History has shown that Java has always managed to move forward and superseed the former.
You can easy check this by reading JEP proposals, discussions on the mailing list, or talks from JVM Language Summit.
There are some notable exceptions though. E.g. invokedynamic from JVM 7 was only really used for Java starting at 8 (with the introduction of lambdas), and was partially introduced to better support dynamically typed languages like Ruby on the JVM.
The languages do benefit from JVM improvements. Scala 2.12 had a significant speed-up due to native lamba support from JVM 8, and if project valhalla ever lands you can bet all JVM languages will be happy to use it.
Basically they will end up with some form of conditional compilation or performance loss emulating those features on other platforms (if at all possible).
That's not true. The javac team is what 5% of all people working on OpenJDK.
I like Rich Hickey's philosophy and personal style, but Clojure just falls short in every aspect as an implementation thereof, in my opinion.
For example, it switched from heavily promoting STM as a concurrency primitive to "app state in atom" to new async/channels.