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: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 inname
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 asList<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 constructfinal int age = 30;
- declaring something as a
var
means 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 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
, and4.0F
are literals for anInt
, aDouble
, aLong
, and aFloat
, respectively; just like in Java"foo"
is a string, just as in JavaUnit
is Scala forvoid
in Java.'foo
creates a symbol (ASymbol
instance), 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 aString
and the third of which is anInt
. Yes, that3
is supposed to be there. There’s alsoTuple2
andTuple16
:) 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 thatfoo
is a reference to an object and not a method name).List("this","is","a","list")
creates aList
of those four strings; nonew
requiredMap("foo" -> 45, "bar" ->76)
creates aMap
ofString
toInt
, nonew
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 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
,Map
andTuple
literals - really, really great.- No more checked exceptions - my prayers are answered
- Type inference - clarity without sacrificing type safety.
The bad:
- if
4
is anInt
,4.0
should be aFloat
. Of course, why is thereInt
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 aMap
and 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).