Scala runs on the JVM, but that doesn't mean we have to write it like Java. Eclipse discourages use of the default package. What are some considerations (e.g. size of project) that determine how code ought to be packaged in Scala?
Scala Projects – Best Practices for Packaging
packagesscala
Related Solutions
There's one thing that you can do concisely and efficiently in Java that you can't in Scala: enumerations. For everything else, even for constructs that are slow in Scala's library, you can get efficient versions working in Scala.
So, for the most part, you don't need to add Java to your code. Even for code that uses enumeration in Java, there's often a solution in Scala that is adequate or good -- I place the exception on enumerations that have extra methods and whose int constant values are used.
As for what to watch out for, here are some things.
If you use the enrich my library pattern, always convert to a class. For example:
// WRONG -- the implementation uses reflection when calling "isWord" implicit def toIsWord(s: String) = new { def isWord = s matches "[A-Za-z]+" } // RIGHT class IsWord(s: String) { def isWord = s matches "[A-Za-z]+" } implicit def toIsWord(s: String): IsWord = new IsWord(s)
Be wary of collection methods -- because they are polymorphic for the most part, JVM does not optimize them. You need not avoid them, but pay attention to it on critical sections. Be aware that
for
in Scala is implemented through method calls and anonymous classes.If using a Java class, such as
String
,Array
orAnyVal
classes that correspond to Java primitives, prefer the methods provided by Java when alternatives exist. For example, uselength
onString
andArray
instead ofsize
.Avoid careless use of implicit conversions, as you can find yourself using conversions by mistake instead of by design.
Extend classes instead of traits. For example, if you are extending
Function1
, extendAbstractFunction1
instead.Use
-optimise
and specialization to get most of Scala.Understand what is happening:
javap
is your friend, and so are a bunch of Scala flags that show what's going on.Scala idioms are designed to improve correctness and make the code more concise and maintainable. They are not designed for speed, so if you need to use
null
instead ofOption
in a critical path, do so! There's a reason why Scala is multi-paradigm.Remember that the true measure of performance is running code. See this question for an example of what may happen if you ignore that rule.
Actually Java 8 doesn't introduce much that will be detrimental to other JVM languages that interop with Java. The work done on Lambdas helped fix a number of small issues around invokedynamic, MethodHandles , MethodReferences etc - but apart from that it's carry on as normal. That said, there's a whole new bunch of APIs that the other JVM languages could potentially call into now. Which ones they'll use by default or not is up to them.
The largest change impacting interop actually came in with Java 7 - with the invokedynamic bytecode that allows dynamic/late binding calls within the JVM - something that was initially designed for the other languages on the JVM. It's since been very usefully adapted for Lamdbas, so as of Java 8, Java will actually start emitting these bytecodes.
Some languages (JRuby for example) are already heavily using invokedynamic, whilst others (Scala, Groovy et al) are still investigating its use or are in the early stages of patching it in. In theory it makes their dynamic calls almost as performant as existing Java invokestatic calls, as opposed to the myriad of slower workarounds they were forced to use in the past.
Java 9 will bring more challenges for JVM languages with project Jigsaw coming into the platform which will be the beginning of the end for traditionally class loading and classpaths for the JVM. The JVM language folks are pretty aware of this and I expect some sensible collaboration to take place.
Best Answer
Scala package best practices are generally the same as Java conventions, according to the Style Guide.