ScalaBasics
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:Stringmeans “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 innamehaving 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 + "," + lastis perfectly valid. - Generics - Type parameters are found inside square braces.
Array[String]is an array of type string (the same asList<String>in Java) - Goodbye final, hello val - declaring something as a
valmeans it cannot be changed;val age = 30is identical to the Java constructfinal int age = 30; - declaring something as a
varmeans it can be changed - 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 toperson toString() - Loose method calling - Parens are optional for zero argument calls.
person toStringis 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, and4.0Fare literals for anInt, aDouble, aLong, and aFloat, respectively; just like in Java"foo"is a string, just as in JavaUnitis Scala forvoidin Java.'foocreates a symbol (ASymbolinstance), which, like Ruby’s symbols, effectively creates a string that is always equal to itself.("foo","bar",45)is aTuple3[String,String,Int], which is to say, a grouping of three values, the first two of which is aStringand the third of which is anInt. Yes, that3is supposed to be there. There’s alsoTuple2andTuple16:) 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.foo("bar")meansfoo.apply("bar")(assuming thatfoois a reference to an object and not a method name).List("this","is","a","list")creates aListof those four strings; nonewrequiredMap("foo" -> 45, "bar" ->76)creates aMapofStringtoInt, nonewrequired 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 execute a class like this isn’t quite the same as Java, however. As an example, you can define an object with a main method, like so:
object MainClassObject {
def main {
println
}
}
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™ 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,MapandTupleliterals - really, really great.- No more checked exceptions - my prayers are answered
- Type inference - clarity without sacrificing type safety.
The bad:
- if
4is anInt,4.0should be aFloat. Of course, why is thereIntvs.Long? It makes no sense. - parens around
ifstatements 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 aMapand send it todoit, 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).