> good fit for any projects where you want to combine these two programming styles.
I'm always a bit wary of this. Its difficult to write a big code base in two different styles, I prefer a language that is mainly in one style. am I wrong?
I find objects are excellent for... well, objects. Things with private state and behaviour. Services, GUI components, and the like. Functions and records are excellent for business data and the transformations of business data. ¿Por que no los dos?
> Its difficult to write a big code base in two different styles, I prefer a language that is mainly in one style.
Not all problems are amenable to a single paradigm. Functional idioms are well suited to composing small systems, object-like abstraction is well suited to composing large systems and services. Note, object-like, not necessarily object-oriented in the Java sense.
I've never used kotlin, but after reading the article, I wondered how it could be possible for kotlin to be null-safe and interoperable with Java at the same time. Turns out it's not [1]. Kotlin's null vs non-null types seem to be semantically the same as option vs non-option (as in scala). However, Scala allows any variable to be null separately from the type system, whereas Kotlin does not. It's not clear to me that Kotlin's approach is preferable here. Kotlin code that interfaces with Java gives the illusion of null-safety, but won't actually provide it. Scala does not attempt to provide this guarantee, which I don't think any language that interoperates with java can ever provide.
This feels like a trad-off between ease-of-use/adoption. It's effectively undefined behavior to reference a nullable type from Java. Another way to consider this is that it's not necessarily worse than working natively in Java, but it can over time be better. This trade-off seems reasonable, as there is no great answer to this problem, but it's almost identical to Java's auto-unboxing of Integer types to int.
You can annotate Java code with @Nullable annotations. Kotlin will understand it and interop will be safe. Spring does it for example, AFAIK Guava does it as well. It won't work with Scala.
Another advantage over Scala is that Kotlin compiler puts null checks on boundaries between Java and Scala, so even if your code pretending to be safe breaks in runtime, you'll catch error as soon as possible, this null won't leak into your internals to bite you tomorrow.
But that's certainly a thing that could be improved. Majority of Java parameters/return values nullability could be automatically inferred by analyzing bytecode.
Interesting. A bit worse than Swift and Objective-C. Objective-C has to promise `nonnull` otherwise it's shown as `ObjectType!` which basically means we treat it as non-null but it could be null and can be checked for null.
Methods marked `nonnull` can still be nil sometimes, it's just a promise. Hard bugs to fix. Found one in an Apple framework where I could not think of anything else than comparing the address with 0x00000000 to see if it was nil.
That's wrong, a lot of JDK api doesn't return null (and a lot of API throws NPE for null arguments). Assuming that everything can return or take null would make Kotlin code unnecessary verbose. It's a valid approach, but not the most pragmatic one.
I assume it inserts an automatic nullcheck [1] if you assign the return value of a java method into a non-null kotlin variable. You might still see NPEs but they happen exactly at the interop boundary between java and kotlin. When you do get an NPE the fix is obvious and trivial to implement.
With scala the NPE could appear after the null crossed the java/scala boundary deep into scala code where you'd assume it should be impossible to get an NPE. It can sometimes be hard to fix because the problem is far away from the cause.
>If we choose a non-null type, the compiler will emit an assertion upon assignment. This prevents Kotlin's non-null variables from holding nulls. Assertions are also emitted when we pass platform values to Kotlin functions expecting non-null values etc. Overall, the compiler does its best to prevent nulls from propagating far through the program (although sometimes this is impossible to eliminate entirely, because of generics).
I have been coding in Kotlin and using the interopt for various libraries. Typically you want to model things interacting with what Kotlin calls “platform types” as nullable.
So for JPA entities, each field is marked as nullable, because in Java it is. If we need a null checked version we map it from the nullable fields object to a object that has been null checked and has non-nullable fields (where appropriate).
Wrappers can be written to interact with more traditional Java libraries that do a similar null check and mapper, keeping platform types from propergating intro other layers of the system.
Platform types make interopt way easier, but if you are concerned with null safety you have to write some code to deal with them.
Meanwhile, there are many other modern ML derivatives (e.g. Ocaml, Rust) which aren't encumbered by the limitations of VMs designed for wholly-imperative languages.
To me it seems that while the two languages share some superficial similarities, they couldn't be more different from one another, to the point of being incomparable.
Kotlin is a language that is designed very much in accordance with the "Java philosophy"[1], which states:
Java is a blue collar language. It’s not PhD thesis material but a language for a job. Java feels very familiar to many different programmers because I had a very strong tendency to prefer things that had been used a lot over things that just sounded like a good idea.
Scala has a diametrically opposed design philosophy. It is very much PhD thesis material (multiple PhD theses), was built to study and experiment with novel ideas in language design, which are very unfamiliar, and happy to adopt things that are untried because they sound like a good idea and may be worth a try; it is decidedly adventurous, as opposed to the mostly conservative Kotlin.
So the choice between the two should be first and foremost be about which of these very different philosophies is the right one for your project and team. Comparing them feature by feature (even if a feature is a generally broad one, like "how easy it is to learn", is ultimately misleading) is misleading. Comparing a car and a tank feature by feature may give the impression that there is a wide overlap between them, and that they may be largely interchangeable, while, in fact, they are very different beasts, and rarely interchangeable.
Exactly. I've been researching Kotlin as a Java replacement at my company and would like to promote it as an all-around, traditional language. In my experience Scala is favored by language nerds (not derogatory!) and their code, while fabulously concise and clever, was largely unreadable outside of their clique and used paradigms that are bizarre to even seasoned developers.
Take a look at The Guardian newspaper's github repository for some professional Scala. It ain't pretty - implicits all over the place, liberally mixed with Cats and Scalaz. This is Scala's big problem - taken in isolation Scala-isms are comprehensible but it's the way the cleverness composes that leads to a big ball of mud. Add to that the tendency of Scala connoisseurs to throw-in Cats and Scalaz at every turn and you have a recipe for disaster.
I'm a Scala fan, so know that up front, but I don't think Scala is unreadable outside of language fanatics, but the language itself is definitely more complicated than Java/Kotlin/Go etc.
We've had a lot of success bringing people unfamiliar with the language (even with heavy usage of Scalaz) because we try to maintain the right ratio of "Scala experts" to "new to Scala". We end up with 1 to 7 more or less, and it seems to work well.
As long as there's enough resources to steer people away from writing ugly code, the payoff can be quite nice. I have never seen a null pointer exception, almost all of the issues we see in staging/dev are related to JSON/REST,and the only issues we've seen in production have been performance/latency related. Scala really allows us to narrow down the type of bugs we get.
The problem with Scala is that it is so expressive and powerful that it is really easy to write unreadable code, especially when delving into the heavy functional side. Scala is the C++ of the JVM.
There will be programmers that want to use every feature all the time, and while this happens with every language, the most featureful ones suffer the most from this.
Yes, the problem with lack of clarity is more often than not the fault of the API designer, not the language. Non-traditional method names like ~%>$ or whatever should be done in a very clear and easy to understand way; if not, that's a feature of the language that was used poorly by the software engineer.
Scala actually has a very consistent and simple syntax which after some initial learning phase is very easy to follow.
The standard library on the other hand, like many APIs which are written in idiomatic Scala, can be difficult to understand, especially at first. I don't admit to understanding it anywhere near as well as I do the Java standard library.
But the issues with Scala in this area is more akin to finding issues with the Java standard library (there are tons!), rather than Java as a language or a VM (two other things which are also correctly referred to as 'Java')
One of the biggest humps I had when getting into Scala full time was getting my head around the fact that many of the features of Scala actually occur at compile time, which as a Java veteran was something that took getting used to.
> Yes, the problem with lack of clarity is more often than not the fault of the API designer, not the language.
Well, a language that enables unreadable cleverness can be said to be at fault. This is why languages, like Kotlin, that follow the Java philosophy, intentionally try to avoid introducing primitive constructs (regardless of whether you believe they are "intrinsically" "simple") that give rise to such cleverness, even at the cost of what others may call expressiveness. Valuing expressiveness over readability (which I here define to be no-cleverness) or vice versa is ultimately a matter of personal preference, but it is a value judgment that's made by the language, and languages that differ in the priorities of their values are very different from one another. Just as the difference between a pure language that guarantees (for the most part) immutability vs. a language that doesn't (even though no one is stopping library designers from writing only pure functions) is big, so is the difference between a language that guarantees (for the most part) readability vs. one that doesn't.
The article seems to paint Kotlin as not really much of a functional language as Scala is but more of a Java replacement. This is just not true. Both languages will not stop you from writing imperative code just as much as either can be used for a very functional style of programming.
It really comes down to the caliber of developer and not the language choice here.
seems very elitist to say functional vs imperative depends on the caliber of the developer. there's plenty of reasons to choose either paradigm. language choice is a reasonable factor. just because you like OO doesn't mean you are bad and just because you like functional doesn't mean you are good
I think OO when done right looks very much like FP. The problem is that OOP is just as hard as FP to write since most languages that claim to be OO languages are actually heavily procedural in nature.
While kotlin doesn't have random symbols as operators, it does have inline functions, which look pretty good too, and are especially useful when designing DSLs.
"Be aware, however, that inlining duplicates the function body at each call site, so heavy use of the ‘inline’ keyword can cause your code to grow out of control."
I didn't quite understand this part. If the code is being inlined on compilation does it matter? I'm assuming the comment meant the output jar file?
I think it just means that a unique binary representation of the inlined code gets created and embedded into the compilation output for each usage of the inlined code, which can then cause the compiled output to expand in size.
What isn't mentioned is the tooling. The Scala compiler and sbt are atrocious. If you move to Scala you'd better get the most massive machine you can find and be prepared to deal with the monstrosity that is sbt.
I don't think the number of Stack Overflow questions is a good indication. Given the difference in age and Scala's use of features unfamiliar to many programmers I'd expect it to generate more questions from (for example) people switching from Java, especially since those unfamiliar features are probably only known to people like Haskell developers who are rare bunch themselves.
Kotlin being a bit more of a "Java done right", a bit less radical, maybe generates less confusion.
It might also be a sign of Kotlin's documentation being better.
I thought the article was pretty weak, it doesn't really go into much detail into how things like higher-kinded types actually affect Scala programming and why you might miss them (or not) in Kotlin, but does take the time to note that Kotlin needs an extra keyword on the constructor arguments for data classes, something which is almost completely irrelevant (and, IIRC, comes from Kotlin's primary constructor syntax so is a reuse of a more widely applicable pattern).
I don't think I could come away from this with an idea of which one I should learn and use, as it claims.
I see a clear pro Scala tendency in this article. Take for example this statement:
> In addition, Scala includes features that you won’t find in either Kotlin or Java, such as full support for pattern matching, macros, and higher-kinded types, which makes Scala ideal for big data processing tasks such as: graph analysis, aggregation computations, and complex, mathematically-focused modelling (e.g. medical modelling.)
This statement is unfortunately not backed by any explanation.
Kotlin has less Stackoverflow questions, but there is also less need for explanation.
Limited operator overloading in Kotlin is a good thing! I've seen way to many Scala with completely absurd and unreadable opertors.
Having worked with both Kotlin and Scala, I see Kotlin as much more pragmatic, what means real world suitable. While Scala was engineered with programming language research in mind (not an ivory tower language like Haskell, though), Kotlin considers more practical aspects like tool support or long-term maintainability. The Scala compiler is, for example, relatively slow. And what about binary (in)compatility in Scala? No word in the article. What about the imminent breaking change with Scala 3 (aka Dotty)?
Scala macros are problematic for tool support. Kotlin will probably get some kind of tool friendly meta-programming, but deliberately not macros.
> Kotlin may be widely considered the easier language to learn, but if it doesn’t have all the features you need, then those few hours spent familiarizing yourself with the Kotlin syntax was time that you could have spent starting to learning a language that does give you the functionality you need.
That may be true for some features, but Scala is a pretty complex beast with many advanced features, which are not only hard to learn, but which also make the code hard to understand or modify. Think of implicit conversions, implicit parameters, which can make it hard to understand what is going on by looking at the code.
Kotlin is much more readable in general: constructos are just named `cunstructor`, init blocks are called `init`, variadic argument are called `vararg`, annotations for co- and contravariance are called `in` and `out`. Scala has to offer method signatures like the following:
flatten[U](implicit ev: <:<[T, Try[U]]): Try[U]
Don't get me wrong, I don't want do condemn Scala and like it in principle, but I think that Kotlin is the better choice in most cases.
This is actually a very good example how scala can make simple things look confusing by trying extra hard to make things look simple. In reality this code simply means that compiler needs to know how to convert T into a Try[U], but the abstraction looks leacky and confusing, partially because it exposes compiler generxated typeclass <:<:
On the other hand, it never fails to amaze me how java users who are willing to accept the magic of java frameworks get so worked up over scala's presumed complexity
46 comments
[ 3.4 ms ] story [ 101 ms ] threadI'm always a bit wary of this. Its difficult to write a big code base in two different styles, I prefer a language that is mainly in one style. am I wrong?
In a situation like that, the ability to combine two styles with a relatively low impedance mismatch is very valuable.
Not all problems are amenable to a single paradigm. Functional idioms are well suited to composing small systems, object-like abstraction is well suited to composing large systems and services. Note, object-like, not necessarily object-oriented in the Java sense.
[1] https://kotlinlang.org/docs/reference/null-safety.html
This feels like a trad-off between ease-of-use/adoption. It's effectively undefined behavior to reference a nullable type from Java. Another way to consider this is that it's not necessarily worse than working natively in Java, but it can over time be better. This trade-off seems reasonable, as there is no great answer to this problem, but it's almost identical to Java's auto-unboxing of Integer types to int.
Another advantage over Scala is that Kotlin compiler puts null checks on boundaries between Java and Scala, so even if your code pretending to be safe breaks in runtime, you'll catch error as soon as possible, this null won't leak into your internals to bite you tomorrow.
But that's certainly a thing that could be improved. Majority of Java parameters/return values nullability could be automatically inferred by analyzing bytecode.
Methods marked `nonnull` can still be nil sometimes, it's just a promise. Hard bugs to fix. Found one in an Apple framework where I could not think of anything else than comparing the address with 0x00000000 to see if it was nil.
With scala the NPE could appear after the null crossed the java/scala boundary deep into scala code where you'd assume it should be impossible to get an NPE. It can sometimes be hard to fix because the problem is far away from the cause.
[1] https://kotlinlang.org/docs/reference/java-interop.html#null...
>If we choose a non-null type, the compiler will emit an assertion upon assignment. This prevents Kotlin's non-null variables from holding nulls. Assertions are also emitted when we pass platform values to Kotlin functions expecting non-null values etc. Overall, the compiler does its best to prevent nulls from propagating far through the program (although sometimes this is impossible to eliminate entirely, because of generics).
So for JPA entities, each field is marked as nullable, because in Java it is. If we need a null checked version we map it from the nullable fields object to a object that has been null checked and has non-nullable fields (where appropriate).
Wrappers can be written to interact with more traditional Java libraries that do a similar null check and mapper, keeping platform types from propergating intro other layers of the system.
Platform types make interopt way easier, but if you are concerned with null safety you have to write some code to deal with them.
Kotlin is a language that is designed very much in accordance with the "Java philosophy"[1], which states:
Java is a blue collar language. It’s not PhD thesis material but a language for a job. Java feels very familiar to many different programmers because I had a very strong tendency to prefer things that had been used a lot over things that just sounded like a good idea.
Scala has a diametrically opposed design philosophy. It is very much PhD thesis material (multiple PhD theses), was built to study and experiment with novel ideas in language design, which are very unfamiliar, and happy to adopt things that are untried because they sound like a good idea and may be worth a try; it is decidedly adventurous, as opposed to the mostly conservative Kotlin.
So the choice between the two should be first and foremost be about which of these very different philosophies is the right one for your project and team. Comparing them feature by feature (even if a feature is a generally broad one, like "how easy it is to learn", is ultimately misleading) is misleading. Comparing a car and a tank feature by feature may give the impression that there is a wide overlap between them, and that they may be largely interchangeable, while, in fact, they are very different beasts, and rarely interchangeable.
[1]: http://dl.acm.org/citation.cfm?id=620728
We've had a lot of success bringing people unfamiliar with the language (even with heavy usage of Scalaz) because we try to maintain the right ratio of "Scala experts" to "new to Scala". We end up with 1 to 7 more or less, and it seems to work well.
As long as there's enough resources to steer people away from writing ugly code, the payoff can be quite nice. I have never seen a null pointer exception, almost all of the issues we see in staging/dev are related to JSON/REST,and the only issues we've seen in production have been performance/latency related. Scala really allows us to narrow down the type of bugs we get.
There will be programmers that want to use every feature all the time, and while this happens with every language, the most featureful ones suffer the most from this.
Scala actually has a very consistent and simple syntax which after some initial learning phase is very easy to follow.
The standard library on the other hand, like many APIs which are written in idiomatic Scala, can be difficult to understand, especially at first. I don't admit to understanding it anywhere near as well as I do the Java standard library.
But the issues with Scala in this area is more akin to finding issues with the Java standard library (there are tons!), rather than Java as a language or a VM (two other things which are also correctly referred to as 'Java')
One of the biggest humps I had when getting into Scala full time was getting my head around the fact that many of the features of Scala actually occur at compile time, which as a Java veteran was something that took getting used to.
Well, a language that enables unreadable cleverness can be said to be at fault. This is why languages, like Kotlin, that follow the Java philosophy, intentionally try to avoid introducing primitive constructs (regardless of whether you believe they are "intrinsically" "simple") that give rise to such cleverness, even at the cost of what others may call expressiveness. Valuing expressiveness over readability (which I here define to be no-cleverness) or vice versa is ultimately a matter of personal preference, but it is a value judgment that's made by the language, and languages that differ in the priorities of their values are very different from one another. Just as the difference between a pure language that guarantees (for the most part) immutability vs. a language that doesn't (even though no one is stopping library designers from writing only pure functions) is big, so is the difference between a language that guarantees (for the most part) readability vs. one that doesn't.
https://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hi...
I didn't quite understand this part. If the code is being inlined on compilation does it matter? I'm assuming the comment meant the output jar file?
(just in case he writes a new article)
Kotlin being a bit more of a "Java done right", a bit less radical, maybe generates less confusion.
It might also be a sign of Kotlin's documentation being better.
I thought the article was pretty weak, it doesn't really go into much detail into how things like higher-kinded types actually affect Scala programming and why you might miss them (or not) in Kotlin, but does take the time to note that Kotlin needs an extra keyword on the constructor arguments for data classes, something which is almost completely irrelevant (and, IIRC, comes from Kotlin's primary constructor syntax so is a reuse of a more widely applicable pattern).
I don't think I could come away from this with an idea of which one I should learn and use, as it claims.
> In addition, Scala includes features that you won’t find in either Kotlin or Java, such as full support for pattern matching, macros, and higher-kinded types, which makes Scala ideal for big data processing tasks such as: graph analysis, aggregation computations, and complex, mathematically-focused modelling (e.g. medical modelling.)
This statement is unfortunately not backed by any explanation.
Kotlin has less Stackoverflow questions, but there is also less need for explanation.
Limited operator overloading in Kotlin is a good thing! I've seen way to many Scala with completely absurd and unreadable opertors.
Having worked with both Kotlin and Scala, I see Kotlin as much more pragmatic, what means real world suitable. While Scala was engineered with programming language research in mind (not an ivory tower language like Haskell, though), Kotlin considers more practical aspects like tool support or long-term maintainability. The Scala compiler is, for example, relatively slow. And what about binary (in)compatility in Scala? No word in the article. What about the imminent breaking change with Scala 3 (aka Dotty)?
Scala macros are problematic for tool support. Kotlin will probably get some kind of tool friendly meta-programming, but deliberately not macros.
> Kotlin may be widely considered the easier language to learn, but if it doesn’t have all the features you need, then those few hours spent familiarizing yourself with the Kotlin syntax was time that you could have spent starting to learning a language that does give you the functionality you need.
That may be true for some features, but Scala is a pretty complex beast with many advanced features, which are not only hard to learn, but which also make the code hard to understand or modify. Think of implicit conversions, implicit parameters, which can make it hard to understand what is going on by looking at the code.
Kotlin is much more readable in general: constructos are just named `cunstructor`, init blocks are called `init`, variadic argument are called `vararg`, annotations for co- and contravariance are called `in` and `out`. Scala has to offer method signatures like the following:
Don't get me wrong, I don't want do condemn Scala and like it in principle, but I think that Kotlin is the better choice in most cases.