And that is a huge benefit. Scala collections are really great.
In addition, Scala also has wrappers around Java collections for interop, or you can just use plain Java collections directly.
It doesn't really matter how great they are, it kills JVM interop right there ... and its even worse if it doesn't and you get implicit conversions killing your performance.
This is where there is a bit of bait and switch with the JVM story (applies to a lot of JVM languages) - "language has great feature X" and "use any library from the JVM ecosystem" - often turn out to be mutually exclusive in a practical sense. Groovy is the only JVM language I've found that seems to deliver a real JVM interop story, but that's explicitly because it is designed from the ground up for that.
That's extreme. It really doesn't "kill" interop at all. If you want to convert, convert. There are many cases where you are not calling Java in hot paths and where converting is perfectly acceptable. If you don't want to, then don't and use Java collections directly. You have the best of both worlds depending on what kind of code base and libraries you are dealing with
Also, implicit conversions between Scala and Java collections have been discouraged/deprecated for years now. You should use the explicit conversion when needed, with `.asScala` or `.asJava`. This makes it obvious whether you might pay a price in the conversion.
Finally, your position overlooks the fact that there are solid reasons to use and prefer Scala collections instead of Java collections: they are quite feature-rich compared to Java collections, are immutable by default, while providing mutable collections if you want those as well.
> that's explicitly because it is designed from the ground up for that
Scala was designed for Java interop from the get go. I am not sure how you are suggesting making things better, besides saying that Scala should never have had its own collections. That would take away a huge part of what makes Scala great, in my book.
It's not in a "trivial sense". You can call any Java code from Scala, call Scala code from Java (except when dealing with Scala constructs that don't have direct Java equivalents). Even Java and Scala functions are the same since Java 8/Scala 2.12. I am not sure how much more interoperability you could even wish again, besides saying that Scala should be identical to Scala. And I write this having written Scala for 10 years and used dozens of Java libraries in Scala projects.
> because of its insistence on using its own collections
This reads like Scala is somehow doing this stubbornly against all reasonable arguments. That's not the case. Scala collections have benefits. Maybe this means using Hibernate is not straightforward from Scala. Ok. I don't know. But this doesn't invalidate Scala having its own collections.
There are tradeoffs in everything. We are talking about two languages and how they interoperate. As far as language integrations go, the Java-Scala interop is excellent, in my view.
Have you tried Kotlin yet? If so, what interferes with its JVM interop story in your opinion? I'm happily using Kotlin with several Java libraries, and IIRC, no Kotlin-specific libraries except for the stdlib.
Kotlin's approach amounts to doubling down on null IMO - it actually makes it harder to interoperate with newer JVM code that favours options over nulls (e.g. streams) from Kotlin than from Scala. And since "platform types" are silently treated as non-null, you still get null exceptions at runtime.
> - Scala defines its own set of collection classes, whereas Kotlin has zero-overhead wrappers over the JVM collection types.
Which means Kotlin has no actually immutable collections; a supposedly immutable collection can be silently mutated by another thread in parallel, which can be pretty surprising.
There are definitely things that Kotlin does well, but IME "smoother interop" is mostly a myth.
Tones of ad-hoc features isn't good language design imho, even the features are desirable in isolation. That's the same issue as the biggest problem with PHP or C++.
On the other hand side Scala may seem "complicated" on the surface but it's actually just a bunch of quite simple basic principles, and some syntax sugar on top.
Scala is like math: It's build form simple first principles. Just it offers the means to combine those and create this way almost arbitrary complex abstractions.
One (arguably) negative consequence of this is that Scala's collections don't play nice with Hibernate and similar ORMs. Due to the way they work, both Scala and Hibernate wanted to "take over" your collections, and obviously they cannot do so at the same time. Of course, it's arguable whether this is a flaw with Scala or with Hibernate, but for the programmers who just wants to get things done that's irrelevant.
It used to be a big deal a few years ago, to the point teams in my company decided to either drop Hibernate or drop Scala.
PS: if I remember correctly, early Scala adopters had reached the consensus that ORMs didn't play nice with Scala's FP style anyway, and so using Hibernate was a mistake. Possibly this attitude changed later.
With Doobie you manually write your queries, and then map the results into the objects in your domain model. Nothing is generated for you. OTOH, nothing is hidden and you are free to write queries as optimized and specialized as you need. The real selling point of Doobie is a typesafe API for manipulating and combining queries, and fragments of queries, into larger wholes. This works very well when your application interfaces with a database it doesn't own.
With Slick you get access to a DSL that lets you layout how your tables look. From there Slick offers an api that let's you treat SQL tables as-if they are basically mutable collections, with Slick handling all the SQL generation itself. You also get DDL, so that you can automate db creation and upgrades. This work very well when your application owns and controls the database it is connecting to.
Both of these have diverged from that traditional ORM model. Slick bills itself as FRM, or Functional Relational Mapping. And Doobie is embedded queries on steroids.
I don't remember what the problems were with Slick that leave such a bad feeling when I hear its name -- that was 5 years ago -- but I had problems with Quill just last year. I was trying to use it to generate an efficient "in" query against a two column composite primary key, and nothing seemed to work. Since it uses macro magic, one of my attempts triggered an internal compiler error instead of normal compiler feedback.
I ended up dropping Quill for ScalikeJDBC:
It seems to be less popular/active than other libraries, but it is dead simple to use, even for developers new to Scala. I write exactly the SQL I want just like I would in psql. There is little-to-no magic. I think that the only slightly magical feature I use is variable interpolation into SQL ("SQLInterpolation") that prevents injection attacks. It actually has capabilities to automatically map tables/columns into different structures and generate code for you, but my team doesn't use any of that. We just write SQL.
wow, the bar for "not dead" is really high these days :-)
AND 2019 wasn't really better. 3.3.2 (3.3.3 was mid 2020) was in JUNE 2019 and 3.3.0 was at the beginning of 2019. there won't be a 3.4 anytime soon, if nobody steps up and starts maintaining it, there won't be a 3.4 at all.
slick is heavy on macros it will not survive scala 3
Doobie (optionally with Quill Syntax) would be left and become likely the "Hibernate of Scala-Land".
That's not too bad news imho.
Having said that I think Quill looks nicer (https://getquill.io/) if you want a DSL like that.
https://tpolecat.github.io/doobie/docs/17-Quill.html
That's by far the best DB access layer I've ever worked with.
Having used Hibernate in a Java project, I would argue using Hibernate is always a mistake. Way too much complexity/brokenness for basically no benefit.
I like null coalescing, but Scala uses a more generic way to handle nulls like Options. After working with both, I'm not sure which way I prefer. I do like not having to create new syntax for language features and could be handled with a monad. Async/await is another that can be handled with an IO, Future, ZIO, etc.
Kotlin also side steps the big standard library by using inline functions a lot (in addition to the mentioned advantage if extending existing Java classes).
To really appreciate Kotlin’s design, one should know some Scala.
Scala is positioned to write new code while using old java libs
Kotlin is positioned to write code/libs which can be shared with new java code
The theme is replacement vs co-existing!
- Scala adds an Option type, whereas Kotlin adds nullability checking for existing object types.
- Scala has its own convention for getters and setters, whereas Kotlin automatically turns JVM getters and setters into properties.
- Scala defines its own set of collection classes, whereas Kotlin has zero-overhead wrappers over the JVM collection types.
I haven't tried Kotlin/JS lately, but I expect that Kotlin's strong focus on interop with existing stuff would serve it well there too, especially when it comes to minimizing bundle size.
Scala may be more powerful in some ways, but Kotlin gives me the conciseness I want, with great interop with the huge Java ecosystem.