Skip navigation
ANNOUNCEMENT: community.oracle.com is currently Read only due to planned upgrade until 29-Sep-2020 9:30 AM Pacific Time. Any changes made during Read only mode will be lost and will need to be re-entered when the application is back read/write.

When I write a book, I always imagine who the reader is. Depending on the kind of project, it might be a beginning computer science student, or an experienced engineer starting out with learning a new technology.

Sometimes, it's “myself, as I was a little while ago”. That's how it went with Core Java, which sold a huge number of copies when everyone else wanted just what I wanted too: know how to solve common tasks in a new language. Other books didn't do so well teaching their readers how to develop hierarchies of fruit and animals.

Now I am in the same happy situation with the Scala book that I am writing. There are other Scala books out there, and they are nice books. It's just that they have examples with fruit and animals, and I still don't like those. Even if they show me the mechanics of a feature, they rarely show why I would want to use it. Even worse, unless they are very carefully constructed, the intuition that I have about fruits or animals can lead me seriously astray. So I decided to write my own book.

I find myself referring to my draft when I code in Scala quite a bit, as I need reminders about file handling, pattern matching, or the finer points of traits. Occasionally, a tidbit is in an unexpected place, and I get to move it, since, after all, it is my book.

The chapters are converging nicely, and thanks to modern publishing technology, I can unveil the result incrementally. If you have a Safari subscription, go here. If not, you can get the "A1" level materials for free from typesafe.com here. (A1 is the "beginning application programmer" level from Martin Odersky's Scala levels.) Bugs? Comments? Suggestions? Please leave them here.

I'd like to put in a plug for the technology that makes it possible for me to quickly write and rewrite this material. I write in XHTML, with a simple style sheet that takes care of section numbering, cross-references, notes and tips. Then I use PrinceXML to turn out PDF. It is a great “what you see is what you need” system that gives me control over what I care about—in particular, what is and what isn't code. I could use Docbook and FOP, but that looks far more complex.

PrinceXML is a bit pricey for an individual user, but there is an inexpensive online service, DocRaptor. You make a JSON call with the contents of the document, as a single file with all images embedded as data URIs, and you get the PDF document back. I wrote a script that does the image embedding and that glues the chapters together—using Scala, of course. Scala may not be a scripting language, but it is my favorite language for writing scripts.

I am in the process of revising a CS1 textbook. I made changes requested by users, added snazzy exercises and sample programs, and the publisher sent the draft out to reviewers. A couple of reviewers said in no uncertain terms that I was wrong, wrong, wrong in using double for my examples. I should usefloat instead. Another professor contributed a business problem set that used float where I would have used double, or, if I had been allowed,BigDecimal.

What gives? For financial calculations, floataren't so wonderful. For example,

float unitPrice = 34999.95F;
int quantity = 199;
float totalPrice = unitPrice * quantity; // Off by five cents from the correct value

Clearly, BigDecimal would be the right choice, but they are awful to use in Java.

BigDecimal unitPrice = new BigDecimal("34999.95");
BigDecimal quantity = new BigDecimal("199");
BigDecimal totalPrice = unitPrice.multiply(quantity);

In Scala, you could write BigDecimal("34999.95") * 100 . But that doesn't help me. Nobody uses Scala for their introductory course. Anyway, reviewers were adamant not to use objects and method calls too early. So, BigDecimalwasn't going to fly. But I digress.

Back to float. Even if you don't care about limited precision, they are also awkward. You have to remember to putF after each literal, and you have to cast the results of mathematical methods:

float goldenRatio = 0.5F * (1 + (float) Math.sqrt(5))

For what? Saving four bytes? In a student program that gets executed a handful of times?

I can see the use of float in a 1000 x 1000 matrix, if the added precision isn't needed, to save the storage. Does it save time? I seem to recall that in an Intel processor, when both float and double get extended unless you use strictfp. No reviewer had requested that I cover that :-)

Am I missing the boat here? Is there another reason to usefloat in this day and age, other than saving storage when you have a lot of them? I read through What Every Computer Scientist Should Know About Floating-Point Arithmetic, and was not enlightened. If you usefloat, can you tell me why?

In Scala, you can nest just about anything inside anything. You can define functions inside other functions, and classes inside other classes. Here is a simple example of the latter. (I follow this explanation in a hopefully more intuitive context.)

import collection.mutable._
class Network {
  class Member(val name: String) {
    val contacts = new ArrayBuffer[Member]
  }

  private val members = new ArrayBuffer[Member]

  def join(name: String) = {
    val m = new Member(name)
    members += m
    m
  }
}

Of course, you can do the same in Java:

import java.util.*;
public class Network {
  public class Member {
    private String name;
    private ArrayList<Member> contacts = new ArrayList<>();
    public Member(String name) { this.name = name; }
    public String getName() { return name; }
    public ArrayList<Member> getContacts() { return contacts; }
  }

  private ArrayList<Member> members = new ArrayList<>();

  public Member join(String name) {
    Member m = new Member(name);
    members.add(m);
    return m;
  }
}

But there is a difference. In Scala, each instance has its own class Member, just like each instance has its own field members. Consider two networks.

val chatter = new Network
val myFace = new Network

Now chatter.Member and myFace.Memberare different classes. In contrast, in Java, there is only one inner class Network.Chatter.

The Scala approach is more regular. For example, to make a new inner object, you simply use new with the type name:

val fred = new chatter.Member("Fred")

In Java, you need to use a special syntax.

Member fred = chatter.new Member("Fred");

And in Scala, the compiler can do useful type checking. In our network example, you can add a member within its own network, but not across networks.

val fred = chatter.join("Fred")
val wilma = chatter.join("Wilma")
fred.contacts += wilma // Ok
val barney = myFace.join("Barney") // Has type myFace.Member 
fred.contacts += barney 
  // No—can't add a myFace.Member to a buffer of chatter.Member elements

For networks of people, this behavior probably makes sense. If you don't want it, there are two solutions.

First, you can move the Member type somewhere else. A good place would be the Network companion object.

object Network {
  class Member(val name: String) {
    val contacts = new ArrayBuffer[Member]
  }  
}

class Network {
  private val members = new ArrayBuffer[Network.Member]
  ...
}

Companion objects are used throughout Scala for class-based features, so this is no surprise.

Alternatively, you can use a type projectionNetwork#Member, which means “aMember of any Network”. For example,

class Network {
  class Member(val name: String) {
    val contacts = new ArrayBuffer[Network#Member]
  }
  ...
}

You would do that if you want the fine-grained “inner class per object” feature in some places of your program, but not everywhere.

So, which language is more complex, Scala or Java? Except possibly for the Network#Member syntax, I think Scala wins hands-down. It is more regular, and it offers more functionality at the same time. It does that with a handful of basic principles, systematically applied. (Before you flame me, consider that ”less familiar” is not the same as “more complex”.)

In contrast, with Java, you can see that inner classes were bolted onto an existing language. Did I mention that Java has restrictions on accessing local outer variables in local inner classes? And “static” inner classes? Don't get me going. It's half a chapter in Core Java. Scala doesn't have any of that.