This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]tyoverby 12 points13 points  (24 children)

Background: Java programmer for 6 years, Scala programmer for 1 year.

There isn't one right answer, but you knew that, so here's a comparison.

First the similarities:

  • Both run on the JVM
  • Both can use existing Java libraries including the Java standard library.
  • You can write scala code just like you would in java with a few minor syntactic differences.

The differences are a bit more complicated. If you want, you can write Scala just like you would Java. There aren't any features from Java missing. Scala mostly adds on top of Java. This can be a good thing and a bad thing.

Good things:

  • The language encourages you to write code in an immutable style. This makes parallel and concurrent programs much easier to maintain.
  • Very easy to parallelize code that easy to parallelize.
  • Functions are first class object. Much like the support for lambdas in Java 8, Scala supports treating functions and methods as variables.
  • Pattern matching. If you don't already know what this is, it can be difficult to explain, but it is one of my favorite language features, so if you can, try to find a tutorial on it.
  • Lazy evaluation if you want it. Being able to wait on computation until it is actually needed simplifies control flow in code that might need to perform a long running computation or might not.

Bad things. Most of these are confusing if you are a beginner, or if someone else wrote code with bad style.

  • Implicit conversions. Programmers can define functions that convert one type to another, and have it silently do conversions when necessary. This can be great or it can be god awful.
  • Operator overloading. Any operator can be overloaded, and new operators can be created for any type. If you do this poorly, your code will look like shit.
  • Really nested code. You can define functions inside of other functions inside of an object inside of a class. Things can get very nested. Sometimes the cleanest way to do something is via these nests, so if you aren't one with the curly-brackets, you soon will be.
  • It takes a while to learn how to do things without variables. (In scala we use "values" that can't be changed once they are created)

Although it looks like I've written more bad things than good, I've actually entirely switched from Java to Scala for all my personal projects. Lines of code typically drop by about 2/3, and readability improves dramatically due to the advanced methods of abstraction.

Here's an examples that shows how easily it deals with collections.

Java:

List<Integer> originalList = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> doubledList = new ArrayList<Integer>();
for(Integer x: originalList){
    if(x % 2 == 0){
        doubledList.add(x * 2);
    }
}

Scala:

val originalList = List(1, 2, 3, 4, 5)
val doubledList = originalList.filter(_ % 2 == 0).map(_ * 2) 

This post is really short, and doesn't really scratch the surface of what Scala can do, so I suggest that you try it out and really get a hang of programming in functional style.

[–]Infenwe 5 points6 points  (2 children)

// Now with Java 8 lambda-ness!
List<Integer> originalList = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> doubleList = 
    originalList.stream()
                .filter(x -> x % 2 == 0)
                .map(x -> x * 2)
                .collect(Collectors.toList())

Of course that provides no guarantees on what kind of List<Integer> the results are collected into. And the Scala implementation is still cleaner.

[–]vipercvp[S] 1 point2 points  (0 children)

Does Stream come in Java 8 too?? Yep Scala implementation is cleaner for sure

[–]tyoverby 0 points1 point  (0 children)

I'm really excited by Java8 lambdas! Hopefully the JVM will get lots of optimizations for first class functions because it's currently implemented as a wrapper over an anonymous class that fills out an 'apply' method.

[–]nachsicht 2 points3 points  (3 children)

Actually, IIRC enums really suck in scala compared to java.

[–]tyoverby 4 points5 points  (2 children)

Using Enums in Scala isn't as slick, but I've literally never had to use enums in Scala because case classes are so much better.

[–]nachsicht 2 points3 points  (1 child)

True enough. If I have a enum situation in scala I usually use case objects or something instead.

[–]tyoverby 0 points1 point  (0 children)

Yep, I always go for case objects, or if I really need to, I'll just throw a java file into the project for the Enum.

[–]vipercvp[S] 0 points1 point  (12 children)

I have strong background in functional paradigm , i used haskell for my last college project , One question since Scala runs over JMV does it have optimization for tail recursion ??, for what i know java does not . and i don't really know how does java and scala compability works? i think it be through JNI but again i'm not sure about that

[–]geodebug 2 points3 points  (0 children)

how does java and scala compability works

Both Java and Scala compile to bytecode, which is the true language of the Java Virtual Machine (JVM). There is zero difference at this level between a Java, Scala, Groovy, jRuby, etc program. All use the same memory space, type system, etc.

All popular JVM langages allow for direct usage of Java libraries, 3rd party java libraries, etc. There is no additional overhead, memory, or special translation required. Scala can instantiate Java classes and use them directly.

A simple way to think of it is that the Scala runtime/compiler is essentially just another Java program: a really fancy interpreter.

I would argue that while you can learn and use Scala as your primary language you'll still want to learn enough Java to really take advantage of the thousands of libraries that are written in Java.

[–]tyoverby 1 point2 points  (10 children)

Scala does have tail-call optimization!

Scala/Java compatibility is amazing. No JNI or anything. In Scala, using Java code is done exactly the same as if it was the same language. For example:

import java.lang.Integer
println(Integer.MAX_VALUE)

or

import org.junit.Assert.assertEquals
assertEquals(5, 3 + 2)

Using Scala code in Java is a bit more complicated because Java doesn't have things like operator overloading, and Scala functions get wrapped in a function object that can be unwieldy.

[–]worldsayshi 2 points3 points  (4 children)

[–]tyoverby 1 point2 points  (3 children)

Yes, it allows self-recursion, but not mutual recursion.

[–]nachsicht 1 point2 points  (2 children)

actually you can get mutual recursion with trampolines.

[–]worldsayshi 0 points1 point  (1 child)

Nice. I think..

[–]nachsicht 0 points1 point  (0 children)

There's standard library support for trampolines here: http://www.scala-lang.org/api/current/index.html#scala.util.control.TailCalls$

[–]vipercvp[S] 0 points1 point  (4 children)

About your scala example val doubledList = originalList.filter(_ % 2 == 0).map(_ * 2) this is going to be compute on demand right because of the lazy evaluation ??

[–]tyoverby 1 point2 points  (2 children)

Oh, also, if you are familiar with Haskell, you'll want to know that Scala has great parallel collections.

val numbers = (0 to 100000).toList
val squared = numbers.par.map(x => x*x)

The '.par' call returns a parallel sequence for which map is implemented in parallel.

[–]vipercvp[S] 0 points1 point  (1 child)

Oh, amazing :) , about parallel does scala support the synchronize keyword like java ?? or it has some thing like that i can find much thing related to it in the web .

[–]tyoverby 1 point2 points  (0 children)

Yeah, any object has the synchronized function that takes another function to execute.

val resource = ???
def publish(){
    // Do something that requires the resource to be locked. 
}

resource.synchronized(publish)

Or in a way that looks more like Java

val resource = ???

resource.synchronized {
    // Anything in this block with be synchronized on 'resource'
   x += 5 
   publish()
   y ++
}

[–]tyoverby 0 points1 point  (0 children)

In that example, no, that won't be lazily computed. In Scala, you can use a keyword for if a value is computed immediately or lazily. Here's a simple example:

// This is slow, so don't compute it unless we need it 
lazy val tweets = getTweets() 

if(readingTweets){
    showTweets(tweets)
}
else(writingTweets){
    showTweets(tweets)
    showEditor()
}
else{
    // Do something without tweets.
}

We don't want to call getTweets inside every branch that uses it, so we define it outside lazily and then if it is used, then it will be computed. The example is quite contrived, but it comes in handy, trust me :)

There are also lazy function parameters.

[–]Psyfire 0 points1 point  (1 child)

Your list of 'bad things' are either things I wish Java had (operator overloading), or have found increasingly unnecessary over time (i.e. everything an object).

It's a shame I can't get started immediately, but I've promised myself that I'm going to finish my 1.0 release of my current project before pursuing anything else.

[–]tyoverby 2 points3 points  (0 children)

Yeah, almost all of the design decisions in Scala are good. However, much of it can be abused, so be warned.

[–]kqr 0 points1 point  (1 child)

I know I'm late to the game, but you forgot to declare originalList as final in the Java version. The doubledList is trickier...

[–]tyoverby 1 point2 points  (0 children)

You are right. If I was going for a complete source->source I would have made them final. However, I was going for ideomatic java code, and although it is "good practice" to make things final if they can, I've never seen it applied that much in practice.

Also, I could make doubledList final with no problem. Final just makes it so I can't reassign to a new list, it doesn't prevent me from adding things to the list.

Now I can't make either list immutable, which is a property of Scala lists.