News for hackers. Stuff that matters.
Re:Java's records, Lombok's data, and Kotlin's data classes by valenterry on Friday May 07, 2021 @12:22PM (#27077609)
Scala's case classes are missing in the comparison (only mentioned briefly at the very end). They offer everything that records do and more. Good to see that Java finally catches up a bit.
Re:Java's records, Lombok's data, and Kotlin's data classes by halfmatthalfcat on Friday May 07, 2021 @12:28PM (#27077682)
Scala is usually omitted for one reason or another when Kotlin is compared against Java as a better alternative, which is a shame.
Re:Java's records, Lombok's data, and Kotlin's data classes by aero142 on Friday May 07, 2021 @01:05PM (#27078162)
Scala has to the solution to every problem except the problem of too many features.
Re:Java's records, Lombok's data, and Kotlin's data classes by ernst_klim on Friday May 07, 2021 @03:00PM (#27079579)
> except the problem of too many features

Scala is a pretty simple, concise and coherent language though. Never understood why people deem it has too many features, I write it professionally and never felt so.

At least comparing it to C, C++, Python. Java may be more simple, but you have tons of features added with metaprogramming via dozens of annotations generating lots and lots of boilerplate, Lombok and Spring are examples of that.

Re:Java's records, Lombok's data, and Kotlin's data classes by ragnese on Friday May 07, 2021 @08:13PM (#27082334)
Exactly this. Java-the-language is so simple that Java-in-practice is disgustingly littered with verbose patterns to accomplish really basic abstraction concepts, annotations that may or may not work at runtime, and runtime reflection with unsafe casting because of type-erased generics.

Java codebases are way scarier than Scala.

Re:Java's records, Lombok's data, and Kotlin's data classes by kerblang on Friday May 07, 2021 @03:18PM (#27079830)
> Never understood why people deem it has too many features

I'll start with one (key)word: `implicit`

I agree with your distaste for metaprogramming though.

Re:Java's records, Lombok's data, and Kotlin's data classes by lmm on Friday May 07, 2021 @09:35PM (#27082799)
Implicits are one feature that replace many features in other languages (Kotlin has probably 5 or 6 special features that each do limited subsets of what implicits can do, and still misses important parts of their functionality). There is some legitimate criticism to be made of Scala implicits (though I have yet to see a better alternative), but "too many features" isn't it.
Re:Java's records, Lombok's data, and Kotlin's data classes by lolinder on Friday May 07, 2021 @09:56PM (#27082935)
What Kotlin features do implicits serve to replace? I'm new to Scala and am having trouble imagining when I'd want to use an implicit, so I'm genuinely curious.
Re:Java's records, Lombok's data, and Kotlin's data classes by lmm on Friday May 07, 2021 @10:05PM (#27082987)
Off the top of my head: Extension methods. "with" contexts. Scope functions (by letting you write your own). Many of the things done with kapt (e.g. typeclasses, not that there's a good way to do them in Kotlin). Spring-style autowiring (not part of Kotlin proper, but seemingly the idiomatic way to use it). The magic last parameter lambda syntax thing (by letting you implement the magnet pattern).
Re:Java's records, Lombok's data, and Kotlin's data classes by beerbajay on Saturday May 08, 2021 @10:57AM (#27087699)
Scala implicits are used in a few different places, predominantly in library code where they can for example be used to derive instances of type classes. e.g. in circe:

  import io.circe.syntax._
  List(1, 2, 3).asJson
Where `asJson` requires an instance of an `Encoder`[1] and this Encoder can be derived with the help of implicits.

For you as a normal user, the two common places where you might use implicits are (1) for implicit classes providing syntactic sugar:

  // original
  def doSomething(a: A): B = ???
  val a: A = ???
  val b = doSomething(a)

  // with implicits
  implicit class AImplicits(a: A) {
    def doSomething: B = ???
  }
  val a: A = ???
  val b = a.doSomething
and for (2) implicit conversions. These are a foot-gun, so should be used in limited circumstances. At work, we use case classes in data pipelines then convert these to avro classes on save; there's lots of ways to do this, but as an example if you have an `Optional[Int]` and your avro constructor requires a nullable java `Integer` then `JavaConverters` won't save you and you'll need something like:

  implicit def optIntToInteger(optI: Option[Int]): java.lang.Integer = optI.map(Int.box).orNull
[1] https://circe.github.io/circe/api/io/circe/syntax/package$$E...
Re:Java's records, Lombok's data, and Kotlin's data classes by halfmatthalfcat on Friday May 07, 2021 @03:33PM (#27080001)
You can use Scala without introducing implicits and even if you have to interopt with a library that does require them, it's quite easy to learn how to use them. It's also easy to abuse them but then that's not really Scala's problem.

They are changing implicits in Scala 3 though with the "given" keyword which is more ergonomic.

Re:Java's records, Lombok's data, and Kotlin's data classes by cutler on Friday May 07, 2021 @04:30PM (#27080520)
Scala can't let go of implicits as they're a fundamental part of the language. I just don't believe this Scala 3 fudge to give the impression implicits are not alive and well beneath the surface.
Re:Java's records, Lombok's data, and Kotlin's data classes by esarbe on Saturday May 08, 2021 @05:11AM (#27085298)
Scala 3 takes the most common use cases for implicits and makes them more ergonomic. Implicits are still in the language, but not exposed as concept.

Odersky called the approach for Scala 3 "intent over mechanism."

Re:Java's records, Lombok's data, and Kotlin's data classes by asimpletune on Friday May 07, 2021 @04:08PM (#27080322)
You don’t have to use implicits though, but you’d be super happy they’re there should you ever be in a situation where they’re helpful
Re:Java's records, Lombok's data, and Kotlin's data classes by diroussel on Friday May 07, 2021 @04:41PM (#27080638)
Doesn’t a monad or for comprehension use implicits to find the right CanBuildFrom?

Are you suggesting to use scala without using for comprehensions? Or do you mean you don’t need to write your own?

It’s been a long time since I wrote scala, so may be getting it wrong.

Re:Java's records, Lombok's data, and Kotlin's data classes by valenterry on Friday May 07, 2021 @09:04PM (#27082647)
No it does not. A for-comprehension just requires that map/flatMap methods are available. No implicits or CanBuildFrom needed.
Re:Java's records, Lombok's data, and Kotlin's data classes by joshlemer on Friday May 07, 2021 @08:54PM (#27082584)
CanBuildFrom is gone in the 2.13 collections rewrite
Re:Java's records, Lombok's data, and Kotlin's data classes by ernst_klim on Friday May 07, 2021 @04:18PM (#27080403)
> I'll start with one (key)word: `implicit`

I don't think implicit counts as "too many features" or as something complex. Basically all it does is finding a canonical value in scope for a hole of certain type.

Re:Java's records, Lombok's data, and Kotlin's data classes by kjeetgill on Friday May 07, 2021 @05:17PM (#27080941)
I only worked in Scala briefly so maybe it's coming from Java habits, but implicits were huge pain. When first reading through code you don't really know if that function call you eyed over really has the params you think it does. It makes it WAY harder to track what's derived from what.

Either way, the local Scala guru there said the Scala community was starting to get over implicits.

Re:Java's records, Lombok's data, and Kotlin's data classes by valenterry on Friday May 07, 2021 @09:05PM (#27082654)
I think that's were it comes from: people that briefly worked with Scala in the past.

At some point it was true, but nowadays the problem is solved because IDEs will show you were an implicit is used and where it comes from. Without that, it was indeed more difficult - but also not more difficult than Java's reflection or DI (where you had and have even less help).

Re:Java's records, Lombok's data, and Kotlin's data classes by ernst_klim on Saturday May 08, 2021 @02:20PM (#27089516)
> When first reading through code you don't really know if that function call you eyed over really has the params you think it does.

Yeah, but don't you feel the same pain when using Spring's autowiring? Or python's (or C++ template) default arguments? Or dynamic method dispatching in any OO language, where you don't know what method you actually call? Or late bindings?

I don't see how implicits' implicitness is significantly worse than any other kind of implicitness common in other language.

Re:Java's records, Lombok's data, and Kotlin's data classes by kjeetgill on Sunday May 09, 2021 @04:12AM (#27094201)
I mean me personally? I'm very boilerplate tolerant. I'm not a fan of Dependency Injection/Auto Wiring for similar reasons and I've never found wiring boilerplate to be too painful. In fact I'd love even more explicitness and manual wiring for almost everything like disk, network, or even clock access aka passing capabilities!

Default params are generally fine since they're hidden on the implementation side but explicit if they vary at the caller site.

And even dynamic dispatch I try to use carefully and sparingly. I just like really explicit programs.

Re:Java's records, Lombok's data, and Kotlin's data classes by ernst_klim on Sunday May 09, 2021 @07:05AM (#27095020)
> I'm not a fan of Dependency Injection/Auto Wiring for similar reasons

I see. My point was that such things are pretty common in most contemporary languages and I don't see how Scala is special in this regard.

Yes, unlike Go or Java, implicits are part of the language spec and not some metaprogramming magic on top of it, but I'm not sure it's a bad thing.

Re:Java's records, Lombok's data, and Kotlin's data classes by AzzieElbab on Friday May 07, 2021 @01:11PM (#27078253)
Maybe but scalas case classes are super easy to grasp and require no magic like annotations
Re:Java's records, Lombok's data, and Kotlin's data classes by xenomachina on Friday May 07, 2021 @03:00PM (#27079580)
What annotations are you referring to?
Re:Java's records, Lombok's data, and Kotlin's data classes by AzzieElbab on Friday May 07, 2021 @03:10PM (#27079725)
Lomboks. Seriously, scala case classes are like the very first thing people start using when learning the language. Scala3 enums are even more straightforward
Re:Java's records, Lombok's data, and Kotlin's data classes by xenomachina on Friday May 07, 2021 @04:18PM (#27080407)
The ancestors of your comment mention Kotlin, not Lombok, which is why I asked. Kotlin's data classes are probably the analog to Scala's case classes, and they do not require annotations.
Re:Java's records, Lombok's data, and Kotlin's data classes by scubbo on Friday May 07, 2021 @03:09PM (#27079723)
I'm not the person you were asking, but, presumably, Lombok's annotations.
Re:Java's records, Lombok's data, and Kotlin's data classes by adambatkin on Friday May 07, 2021 @01:59PM (#27078803)
Lombok and Kotlin are both much easier to integrate into existing Java applications and libraries than Scala.
Re:Java's records, Lombok's data, and Kotlin's data classes by lmm on Friday May 07, 2021 @09:38PM (#27082817)
Not so IME. Kotlin's nullable types don't play nice with option-oriented APIs (e.g. Java Streams), and you can't make Java types transparently implement Kotlin interfaces (and there's no equivalent to typeclasses), so using Java types with Kotlin libraries is harder than with Scala libraries.
Re:Java's records, Lombok's data, and Kotlin's data classes by krzyk on Friday May 07, 2021 @02:57PM (#27079548)
Lombok is the problem not a solution (see https://github.com/projectlombok/lombok/issues/2681 regarding support for JDK 16 to understand why) and a ticking time bomb in every project that wants to move past JDK 15/16.

But why do you think Kotlin is easier to integrate than Scala? Both work on JVM.

Re:Java's records, Lombok's data, and Kotlin's data classes by gher-shyu3i on Thursday May 20, 2021 @10:57AM (#27221943)
It's been resolved though.
Re:Java's records, Lombok's data, and Kotlin's data classes by kelnos on Friday May 07, 2021 @03:04PM (#27079654)
I don't see how Kotlin is easier to integrate into an existing Java app than Scala is. They both require adding new dependencies and changing your project build config, and require developers who know the respective new language. That's... about it. They both offer similar levels of interop with Java libraries.

If you want to assert that finding Kotlin developers is easier or that Kotlin is an easier language to learn, sure, that might be the case (I really don't know), but that's not really an integration task.

Re:Java's records, Lombok's data, and Kotlin's data classes by throwpupper on Friday May 07, 2021 @03:13PM (#27079773)
What about the fact that Kotlin collections are fully interoperable with Java collection? That makes the transition significantly easier.
Re:Java's records, Lombok's data, and Kotlin's data classes by lmm on Friday May 07, 2021 @09:42PM (#27082836)
You can use Java collections in Scala just as you do in Kotlin, and in fact interop is easier in Scala since you can write typeclass instances for the Java types whereas there's no equivalent for that in Kotlin.

The real difference is that more of the Kotlin ecosystem uses Java's fundamentally mutable collections compared to the Scala ecosystem, and using actually immutable collections in Kotlin is extremely difficult to the point that essentially no-one does it. IMO that's a bad tradeoff in the long term, but you can absolutely take the same approach in Scala if you really want to.

Re:Java's records, Lombok's data, and Kotlin's data classes by lolinder on Friday May 07, 2021 @10:08PM (#27083017)
I write Kotlin all day and almost exclusively use immutable types. What difficulties with using them are are you referring to?
Re:Java's records, Lombok's data, and Kotlin's data classes by lmm on Saturday May 08, 2021 @12:11AM (#27083786)
Kotlin doesn't have immutable collection types in the standard library (it lets you use a read-only interface but the collection is really still mutable and will be seen as such by any Java code), so if you want actually immutable collections you have to use non-standard collections, and since Kotlin doesn't have typeclasses or implicit conversions it's difficult to interoperate between any non-standard collection library and other Kotlin code.
Re:Java's records, Lombok's data, and Kotlin's data classes by lolinder on Saturday May 08, 2021 @12:52AM (#27083983)
Ah, fair. I've never actually seen that become a problem, but I can see how it would be if I were doing more extensive Java interop.
Re:Java's records, Lombok's data, and Kotlin's data classes by lmm on Sunday May 09, 2021 @01:27AM (#27093475)
Yeah, if all your code and libraries are Kotlin then there's less risk of a collection being mutated under you (though even then, Kotlin gives you no way to write a method that only accepts an immutable collection - you can write a method that accepts a view-only interface, but it will always be possible to pass a mutable collection and mutate it in parallel while that method is running). But of course in that scenario there's also zero benefit from having compatibility with the Java collections.
Re:Java's records, Lombok's data, and Kotlin's data classes by halfmatthalfcat on Friday May 07, 2021 @03:30PM (#27079964)
I believe Scala's are as well, this seems to be a pretty complete list:

https://www.scala-lang.org/api/2.13.5/scala/jdk/javaapi/Coll...

Re:Java's records, Lombok's data, and Kotlin's data classes by balefrost on Friday May 07, 2021 @04:08PM (#27080319)
Kotlin's STDLIB collection types are essentially aliases for the Java types. So while the Scala adapters are low-cost, in Kotlin everything's zero-cost.

One other benefit of that is you maintain object identity. I don't think that Scala's wrappers do that.

Re:Java's records, Lombok's data, and Kotlin's data classes by darksaints on Friday May 07, 2021 @05:01PM (#27080823)
Scala has the full suite of Java collections without any conversion or overhead whatsoever.

But it also has Scala collections. With scala collections you get the full power of the Scala type system, as well as a much richer and full featured collections api. So most scala programmers won't bother with java collections unless they have specific java interop requirements.

The Scala adapters are merely ways of converting java collections to scala collections and vice versa.

Re:Java's records, Lombok's data, and Kotlin's data classes by joshlemer on Friday May 07, 2021 @08:56PM (#27082600)
I think it's a fair complaint that in Scala it is a pain in the ass to deal with Java collections. You have to litter your whole code with `.asScala` and `.asJava`, the java collections don't work with for comprehensions, etc.
Re:Java's records, Lombok's data, and Kotlin's data classes by darksaints on Saturday May 08, 2021 @01:04PM (#27088898)
No, it's not hard. In Scala, you are completely free to use those java collections and you can do it exactly how kotlin programmers do it. You want a java list, without any need to convert back and forth between Scala and Java? Import `java.util.List`. All of the same methods and iterators and expressions and constructs are still there. You get all of the lack of capabilities and grace that the java collections provide. Literally no different from using the same collections in Kotlin.

The problem is that those java collections suck in comparison to the Scala collections. So Scala programmers prefer to use Scala collections. Scala programmers would never willfully use java collections if they don't have to, and if they absolutely have to, they have minimal overhead conversions back and forth. The minimal conversion overhead is the price they're willing to pay to use better collections while maintaining java interoperability.

Re:Java's records, Lombok's data, and Kotlin's data classes by joshlemer on Saturday May 08, 2021 @05:36PM (#27090953)
Except Kotlin enjoys the compatibility with Java, plus it outfits those java collections with extension methods and some compiler tricks to achieve all the same functionality as the Scala collections (in fact, I would say even more self-consistent and useably than in Scala). Just as in Scala, in Kotlin you can use functional transforations that Scala users are so accustomed to:

Kotlin:

    listOf(1,2,3,4)
        .map{i -> i + 1}
        .filter { it % 2 == 0 }
        .flatMap { listOf(it, it * 2, it * 3) }
Kotlin even has a similar take to Scala's views, which they call sequences:

    listOf(1,2,3,4)
        .asSequence()
        .map{i -> i + 1}
        .filter { it % 2 == 0 }
        .flatMap { listOf(it, it * 2, it * 3) }
        .toList()
Is this really so "lacking in capability and grace" compared to Scala? The only think missing is persistent immutable collections, which are implemented in kotlinx.
Re:Java's records, Lombok's data, and Kotlin's data classes by valenterry on Sunday May 09, 2021 @06:46AM (#27094910)
> The only think missing is persistent immutable collections, which are implemented in kotlinx.

You said:

> You have to litter your whole code with `.asScala` and `.asJava`, the java collections don't work with for comprehensions, etc.

So how does kotlinx achieve zero-cost compatibility with Java collections without having something like `.asKotlin` and `.asJava`? Because otherwise there is no difference between Scala and Kotlin in this regards.

Re:Java's records, Lombok's data, and Kotlin's data classes by joshlemer on Sunday May 09, 2021 @04:50PM (#27099598)
because the persistentList/Collection/etc in kotlinx implement the appropriate java collection interfaces:

    import java.util.List;

    public class Foo {
        public static void blah(List<Integer> list) {
        }
    }

Kotlin:

    import kotlinx.collections.immutable.persistentListOf

    fun main(): Unit {
        Foo.blah(persistentListOf(1,2,3))
    }

This compiles fine
Re:Java's records, Lombok's data, and Kotlin's data classes by esarbe on Saturday May 08, 2021 @05:14AM (#27085321)
It's only a problem if you can't decide which part of your project to write with which language.

If I have to use Java, I put it into a separate sub-project and make sure that I have a nice API to interface between the subprojects. `.asJava` and `.asScala` then only appear at very specific places where the interop happens.

Re:Java's records, Lombok's data, and Kotlin's data classes by joshlemer on Saturday May 08, 2021 @11:59AM (#27088291)
What you're describing is in and of itself a severe cost and barrier to the very thing we're describing: interoperability between Java and Scala collections. On the one hand you have Scala where you either have to constantly `.asScala` and `.asJava`, or go your route of ensuring that in any given module only deals with either Scala or Java collections. This may involve additional abstractions or classes to achieve. On the other hand you have Kotlin which just directly, frictionlessly deals with Kotlin/Java collections the same way (in fact, they literally are the same). We're comparing "some small-to-medium cost" against "zero-cost".

Or an other way of saying it is that your approach of walling off modules as either java-collection or scala-collection is kind of like saying "Java and Scala collections work well together, so long as you don't have to use them together too much. If you minimize how much they need to interoperate, the problem is not so bad."

Re:Java's records, Lombok's data, and Kotlin's data classes by esarbe on Tuesday May 11, 2021 @03:40PM (#27122537)
> Or an other way of saying it is that your approach of walling off modules as either java-collection or scala-collection is kind of like saying "Java and Scala collections work well together, so long as you don't have to use them together too much. If you minimize how much they need to interoperate, the problem is not so bad."

Yes, that's actually a very good way to rephrase it. That being said; I myself wouldn't limit that to just the collections; Java and Scala on the language level have excellent interop. For Scala-the-ecosystem the story is a bit different.

Java is not the primary target for most of the Scala libraries. Not even a secondary one, I dare say. (I'm not even sure how you would model a Java API for a library - say; Cats - that uses implicits for the heavy lifting.)

That of course stems for the fact that Scala makes use of concepts that have no correspondence in neither Java or Kotlin, so there will necessarily be something lost in translation.

Re:Java's records, Lombok's data, and Kotlin's data classes by jillesvangurp on Saturday May 08, 2021 @01:07AM (#27084061)
Exactly. Kotlin was actually explicitly designed to be like this and is directly competing with Java as a drop in replacement for it. Consider e.g. the seamless integration into Spring and Android, which both continue to support Java as well. Writing Android applications in Scala is a bit of an uphill battle (but I've heard of people attempting it). Writing Spring applications in Scala is possible in principle, I guess, but it's just not a thing that is very common or that is supported by Spring. Spring and Android have documentation with code samples in both Java and Kotlin, and extensive Kotlin specific stuff in the form of e.g. extension functions. At this point Kotlin is the preferred language for both even though they both maintain compatibility with Java as well and will for years to come.

Spring is about half the server side JVM ecosystem. Android represents a good chunk of frontend usage. Kotlin is a first class citizen for both; Scala just isn't. It has its own frameworks of course but they are kind of niche in comparison.

I think it's great that Java is slowly evolving to have features that other languages have. Kotlin supports Java's records as of this week's 1.5.0 release via an annotation. Meaning that if you have Java code that needs to interact with Kotlin code, you can write a data class that from the Java side looks like a record if you put the right annotation on it. It's a compatibility feature that's only relevant if you are planning to use or support Java. Another notable feature that landed with this week's release include sealed interfaces (it already had sealed classes). You can use both with data classes of course.

Re:Java's records, Lombok's data, and Kotlin's data classes by MichaelMoser123 on Saturday May 08, 2021 @03:27AM (#27084794)
i think Kotlin might be winning over Scala because of better ineroperability with java. https://jelmini.dev/post/java-interoperability-kotlin-vs-sca...
Re:Java's records, Lombok's data, and Kotlin's data classes by mumblemumble on Friday May 07, 2021 @01:59PM (#27078800)
I think that case classes are roughly equivalent to Kotlin data classes for the purposes of this comparison. In particular, one of the extra features they offer is the ability to make fields mutable. Which, in some cases, may be useful, but also means that they aren't, strictly speaking, transparent carriers of immutable data.
Re:Java's records, Lombok's data, and Kotlin's data classes by valenterry on Friday May 07, 2021 @09:11PM (#27082687)
Not only that, but they offer some other features that (to my knowledge) both records and kotlin's data classes don't offer. Which is control over accessibility. E.g. when you have a "NegativeNumber" type and you need to make sure the inner value is actually negative. Then just using having a check in the constructor isn't sufficient in the existence of copy methods (like kotlin) does it.
Re:Java's records, Lombok's data, and Kotlin's data classes by jillesvangurp on Saturday May 08, 2021 @01:15AM (#27084099)
A good rule is that constructors MUST not do work. Writing constructors in Kotlin is possible but not that common. Data classes are typically initialized with just value assignments. Having support for default values also means that it largely removes the need for having multiple constructors (which is very common in Java).

If you need to do validation, there are very decent frameworks that you should use for both Java and Kotlin. We are using a thing called Konform currently. Very nice.

For non negative numbers, you can use the new unsigned numeric types they added in Kotlin with the last release: https://kotlinlang.org/docs/basic-types.html#unsigned-intege...

Re:Java's records, Lombok's data, and Kotlin's data classes by snuxoll on Friday May 07, 2021 @09:55PM (#27082930)
The copy methods that Kotlin generates construct a new instance of the class with the updated fields - so any validation done in the constructor would in fact be done again.
Re:Java's records, Lombok's data, and Kotlin's data classes by valenterry on Friday May 07, 2021 @10:34PM (#27083199)
Yes, that's correct. But instead of catching the error at that point, you would probably rather want to disable these methods from the beginning so that someone cannot even make the mistake of using them and has to go through some custom defined method instead.
Re:Java's records, Lombok's data, and Kotlin's data classes by pron on Friday May 07, 2021 @03:59PM (#27080239)
I don't think they offer more. Deconstructing patterns and "reconstructors" (generalised "withers") are on the way. And Java features are often designed as a complete whole: some of the feature is in the language, some in the core libraries, and some, even, in the VM. In the case of records, they're treated in a special way by the runtime (e.g. in serialisation).
Re:Java's records, Lombok's data, and Kotlin's data classes by valenterry on Friday May 07, 2021 @09:09PM (#27082669)
Well I said "they offer more" and not "they will always offer more". So I stand by what I said.

> In the case of records, they're treated in a special way by the runtime (e.g. in serialisation).

Scala will use them as underlying implementation (just like it will do with value-types, functions and so on).