Another tour of Scala

 
 
 
 

Scala Basics

Viewing old version 88d1f7a513b8d15c872f05bf86d83cad5cdd53e3; View Current

The Gist

There is no tour element to cover all of this stuff, however Local Type Inference and Predefined function classOf cover some of this. At any rate, I think it’s pretty handy to go over before looking at too much code.

My Interpretation

Syntax

Some basics about Scala syntax that aren’t obvious (especially if you are coming from Java)

  • Type Declaration – The type of an object or value comes after the value, using a colon: name:String means “name has the type String”
  • Type Inference – If Scala can figure out the type of something from the context, you don’t need to declare the type (this is called type inference). val name = "Dave" results in name having the type String. This is statically assigned, and not dynamic as it would be in Ruby (e.g.)
  • Adios, semicolons – You don’t need semicolons unless Scala can’t figure out where statements end
  • Method definitions – Methods are defined via the “=” sign after the method signature, and don’t require braces if they are one-liners. def toString = first + "," + last is perfectly valid.
  • Generics – Type parameters are found inside square braces. Array[String] is an array of type string (the same as List<String> in Java)
  • Goodbye final, hello val – declaring something as a val means it cannot be changed; val age = 30 is identical to the Java construct final int age = 30;
  • declaring something as a var means it can be changed
  • Operators Operators can be overloaded (more precisely, the characters you are allowed in a method or function name are much more varied than in Java and you can omit dots and parens in certain situations)
  • Loose method calling – The dot between an object and a method call is optional. person.toString() is identical to person toString()
  • Loose method calling – Parens are optional for zero argument calls. person toString is identical to the two expressions above
  • No more checked exceptions – Scala has no checked exceptions. This makes your code a lot cleaner.

Literals and Syntactic Sugar

  • 4, 4.0, 4L, and 4.0F are literals for an Int, a Double, a Long, and a Float, respectively; just like in Java
  • “foo” is a string, just as in Java
  • Unit is Scala for void in Java.
  • 'foo creates a symbol (A Symbol instance), which like Ruby’s symbols and creates a string that is always equal to itself, essentially.
  • ("foo","bar",45) is a Tuple[String,String,Int], which is to say, a grouping of three values, the first two of which is a String and the third of which is an Int. This is a quick and dirty way to group things, return multiple values, or otherwise pass around related data that you don’t need/want to make a class for.
  • List("this","is","a","list") creates a List of those four strings; no new required
  • Map("foo" -> 45, "bar" ->76) creates a Map of String to Int, new new required and no clumsy helper class.

(There is a lot more syntactic sugar, but this covers some basics)

Structure

You do not need a one-to-one mapping of file to class, as you would in Java. Your .scala files don’t even need to be named like the class they define, or mimic the package structure.

Compiling/Running

scalac and scala work just like their java counterparts.

scalac SomeClass.scala SomeOtherClass.scala
  scala -cp . SomeClass

What happens when you run a class isn’t quite the same as Java, however.

object MainClassObject {
    def main(args: Array[String]) {
      println("Hello world!")
    }
  }
scala -cp . MainClassObject

(There are other ways to do this, but this is a way)

Read/Eval/Print

Like most scripting languages, and unlike most compiled languages, Scala has a REPL (Read/Eval/Print Loop) where you can play around

scala
  Welcome to Scala version 2.7.4.final (Java HotSpot(TM) Client VM, Java 1.5.0_16).
  Type in expressions to have them evaluated.
  Type :help for more information.
  scala> val a = List(1,4,6,87,5,3,9)
  a: List[Int] = List(1, 4, 6, 87, 5, 3, 9)
  scala> val b = 12 :: 34 :: a
  b: List[Int] = List(12, 34, 1, 4, 6, 87, 5, 3, 9)
  scala> b
  res0: List[Int] = List(12, 34, 1, 4, 6, 87, 5, 3, 9)
  scala> a.map((item) => item * item) 
  res2: List[Int] = List(1, 16, 36, 7569, 25, 9, 81)
  scala>^D

My Thoughts on this Feature

The good:

  • REPL – awesome, crucial, and very helpful when learning/prototyping
  • semi-colon – I will not miss you
  • List, Map and Tuple literals – really, really great.
  • No more checked exceptions – my prayers are answered
  • Type inference – clarity without sacrificing type safety.

The bad:

  • if 4 is an Int, 4.0 should be a Float. Of course, why is there Int vs. Long? It makes no sense.
  • parens around if statements should’ve been thrown out with the semi-colon
  • Would’ve been nice to have parens optional for all method calls
  • Would’ve been nice to allow someObj.doit('foo -> "bar", 'blah -> "quux") to automatically create a Map and send it to doit, as Ruby does.

It’s a win by a long shot (though more advanced topics will deal with some syntax quirks that I just don’t get).


Last Updated 08/22/2009 at 09:20:33 AM by davec

blog comments powered by Disqus