First Steps to Scala

来源:互联网 发布:蜘蛛池域名收录 编辑:程序博客网 时间:2024/04/29 22:51

First Steps to Scala

by Bill Venners, Martin Odersky, and Lex Spoon
May 9, 2007

Summary

In this article, you’ll followtwelve steps that are designed to help you understand and gain some basicskills in the Scala programming language.

Scala is a statically typed,object-oriented programming language that blends imperative and functionalprogramming styles. Scala is designed to integrate easily with applicationsthat run on modern virtual machines, primarily the Java virtual machine (JVM).The main Scala compiler, scalac, generates Java class files thatcan be run on the JVM. However, another Scala compiler exists that generatesbinaries that can be run on the .NET CLR, as Scala is designed to integratewith both the Java and .NET worlds. In the Java world, the Scala language canbe used alongside the Java language—either as an alternative to Java—to buildapplications that run on the JVM.

Scala was developed starting in2003 by Martin Odersky’s group at EPFL, Lausanne, Switzerland.Previously, Martin had been active in the Java field. He co-designed the firstversion of Java generics and was the original author of the current javac compiler. The work on Scala was motivated by thedesire to overcome limitations imposed by backwards compatibility with Java. SoScala is not a superset of Java, but it retains seamless interoperability.

One reason you might want to useScala is that it allows you to increase your productivity compared to Javawhile leveraging JVM execution speed, your existing investments in Java code,knowledge, and the vast array of APIs available for the JVM. It has theconciseness of a dynamic language like Ruby or Python, but it is staticallytyped, like Java. Another reason is that Scala comes with an Erlang-like Actorslibrary that greatly simplifies concurrent programming, but runs on the JVM.

In Italian, Scala means staircase.In this article, we’ll take you up twelve steps that will help you startbecoming skilled in Scala. The best way to make use of this article is to tryeach example out with the Scala interpeter or compiler. Step 1 explains how todownload and install the Scala distribution.

Step 1. Download and install Scala

To run the examples in thisarticle, you should download Scala from the Scala Downloads page. The examples in this article were run withScala version 2.5.0-RC1, so make sure you download a version at least as recentas 2.5.0-RC1. Once you download an archive file, create a directory whereveryou prefer (perhaps named scala), and unzip (or untar, etc.) thearchive file in that empty directory. Among the subdirectories created will bethe bin directory that contains theScala executables, including the compiler and interpeter. To make Scalaconvenient to use, add the full pathname of the bin directory to your PATH environment variable. The only other requirementyou’ll need to fulfill is an installation of Java 1.4 or above, which you candownload from http://java.sun.com/. You can also use Scala viaplug-ins for Eclipse and IntelliJ, but for the steps in this article, we’llassume you’re using the Scala distribution from scala-lang.org.

Step 2. Learn to use the Scala interpreter

The easiest way to get started withScala is by using the Scala interpreter, which is an interactive “shell” forwriting Scala expressions and programs. Simply type an expression into the interpreterand it will evaluate the expression and print the resulting value. Theinteractive shell for Scala is simply called scala. You use it like this:

$ scala
This is an interpreter for Scala.
Type in expressions to have them evaluated.
Type :help for more information.
 
scala>

After you type an expression, suchas 1 + 2, and hit return:

scala> 1 + 2

The interpreter will print:

unnamed0: Int = 3

This line includes:

·     anautomatically assigned or user-defined name to refer to the computed value (unnamed0)

·     acolon (:)

·     thetype of the expression and its resulting value (Int)

·     anequals sign (=)

·     thevalue resulting from evaluating the expression (3)

The type Int names the class Int in the package scala.Values of this class are implemented just like Java’s int values. In fact, Scala treats int as an alias for scala.Int. More generally, all of Java’s primitive types aredefined as aliases for classes in the scala package.For example, if you type boolean in a Scala program, the typeyou’ll actually get is scala.Boolean. Or if you type float, you’ll get scala.Float. When you compile your Scala code to Java bytecodes, however,Scala will compile these types to Java’s primitive types where possible to getthe performance benefits of Java’s primitive types.

The unnamedX identifier may be used in later lines. Forinstance, since unnamed0 was set to 3previously, unnamed0 *3 will be 9:

scala> unnamed0 * 3
unnamed1: Int = 9

To print the necessary, but notsufficient, Hello,world! greeting, type:

scala> println("Hello, world!")
Hello, world!
unnamed2: Unit = ()

The type of the result hereis scala.Unit, which is Scala’s analogue to void in Java. The main difference between Scala’s Unit and Java’s void isthat Scala lets you write down a value of type Unit, namely (),whereas in Java there is no value of type void.(In other words, just as 12, and 3,are potential values of type int inboth Scala and Java, () is the one and only value oftype Unit in Scala. By contrast, thereare no values of type void in Java.) Except forthis, Unitand void are equivalent. In particular, every void-returning method in Java is mapped to a Unit-returning method in Scala.

Step 3. Define some variables

Scala differentiates between vals, variables that are assigned once and never change,and vars, variables that may change overtheir lifetime. Here’s a val definition:

scala> val msg = "Hello, world!"
msg: java.lang.String = Hello, world!

This introduces msg as a name for the value "Hello world!". The type of the value aboveis java.lang.String, because Scala strings are alsoJava strings. (In fact every Java class is available in Scala.)

This example also points out animportant and very useful feature of Scala: type inference. Notice that younever said the word java.lang.String or even String in the val definition.The Scala interpreter inferred the val‘stype to be the type of its initialization assignment. Since msg was initialized to "Hello, world!", and since "Hello, world!" is type java.lang.String, the compiler gave msg the type java.lang.String.

When the Scala interpreter (orcompiler) can infer a type, it is usually best to let it do so rather than fillthe code with unnecessary, explicit type annotations. You can, however, specifya type explicitly if you wish. (For example, you may wish to explicitly specifythe types of public members of classes for documentation purposes.) In contrastto Java, where you specify a variable&8217;s type before its name, in Scalayou specify a variable’s type after its name, separated by a colon. Forexample:

scala> val msg2: java.lang.String = "Hello again, world!"
msg2: java.lang.String = Hello, world!

Or, since java.lang types are visible with their simple names in Scalaprograms, simply:

scala> val msg3: String = "Hello yet again, world!"
msg3: String = Hello yet again, world!

Going back to our original msg, now that it is defined, you can then use the msg value as you’d expect, as in:

scala> println(msg)
Hello, world!
unnamed3: Unit = ()

What you can’t do with msg, given that it is a val nota var, is reassign it. For example, see how the interpretercomplains when you attempt the following:

scala> msg = "Goodbye cruel world!"
<console>:5 error: assignment to non-variable 
  val unnamed4 = {msg = "Goodbye cruel world!";msg}

If reassignment is what you want,you’ll need to use a var, as in:

scala> var greeting = "Hello, world!"
greeting: java.lang.String = Hello, world!

Since greeting is a variable (defined with var) not a value (defined with val), you can reassign it later. If you are feeling grouchylater, for example, you could change your greeting to:

scala> greeting = "Leave me alone, world!"
greeting: java.lang.String = Leave me alone, world!

Step 4. Define some methods

Now that you’ve worked with Scalavariables, you’ll probably want to write some methods. Here’s how you do thatin Scala:

scala> def max(x: Int, y: Int): Int = if (x < y) y else x
max: (Int,Int)Int

Method definitions start with def instead of val or var. The method’s name, in this case max, is followed by a list of parameters in parentheses. Atype annotation must follow every method parameter, preceded by a colon in theScala way, because the Scala compiler (and interpreter, but from now on we’lljust say compiler) does not infer method parameter types. In this example, themethod named max takes two parameters, x and y,both of type Int. After the close parenthesisof max‘s parameter list you’ll find another “: Int” type specifier. This one defines the result type ofthe max method itself.

Sometimes the Scala compiler willrequire you to specify the result type of a method. If the method is recursive1, for example, you must explicitly specify the methodresult type. In the case of max however,you may leave the result type specifier off and the compiler will infer it.Thus, the max method could have beenwritten:

scala> def max2(x: Int, y: Int) = if (x < y) y else x
max2: (Int,Int)Int

Note that you must alwaysexplicitly specify a method’s parameter types regardless of whether youexplicitly specify its result type.

The name, parameters list, andresult type, if specified, form a method’s signature.After the method’s signature you must put an equals sign and then the body ofthe method. Since max‘s body consists of just onestatement, you need not place it inside curly braces, but you can if you want.So you could also have written:

scala> def max3(x: Int, y: Int) = { if (x < y) y else x }
max3: (Int,Int)Int

If you want to put more than onestatement in the body of a method, you must enclose them inside curly braces.

Once you have defined a method, youcan call it by name, as in:

scala> max(3, 5)
unnamed6: Int = 5

Note that if a method takes noparameters, as in:

scala> def greet() = println("Hello, world!")
greet: ()Unit

You can call it with or withoutparentheses:

scala> greet()
Hello, world!
unnamed7: Unit = ()
 
scala> greet
Hello, world!
unnamed8: Unit = ()

The recommended style guideline forsuch method invocations is that if the method may have side effects4, you should provide the parentheses even if thecompiler doesn’t require them. Thus in this case, since the greet method prints to the standard output, it has sideeffects and you should invoke it with parentheses to alert programmers lookingat the code.

Step 5. Write some Scala scripts

Although Scala is designed to helpdevelopers build large systems, it also scales down nicely such that it feelsnatural to write scripts in it. A script is just a sequence of statements in afile that will be executed sequentially. (By the way, if you’re still runningthe scala interpreter, you can exit it by entering the :quit command.) Put this into a file named hello.scala:

println("Hello, world, from a script!")

then run:

>scala hello.scala

And you should get yet anothergreeting:

Hello, world, from a script!

Command line arguments to a Scalascript are available via a Scala array named args. In Scala, arrays are zero based, as in Java, but youaccess an element by specifying an index in parentheses rather than squarebrackets. So the first element in a Scala array named steps is steps(0), not steps[0]. To try this out, type thefollowing into a new file named helloarg.scala:

// Say hello to the first argument
println("Hello, " + args(0) + "!")

then run:

>scala helloarg.scala planet

In this command, "planet" is passed as a command lineargument, which is accessed in the script as args(0). Thus, you should see:

Hello, planet!

Note also that this script includeda comment. As with Java, the Scala compiler will ignore charactersbetween // and the next end of line, aswell as any characters between /* and */. This example also shows strings being concatenatedwith the + operator. This works as you’dexpect. The expression "Hello," + "world!" will result in the string "Hello, world!".

By the way, if you’re on someflavor of Unix, you can run a Scala script as a shell script by prepending a“pound bang” directive at the top of the file. For example, type the followinginto a file named helloarg:

#!/bin/sh
exec scala $0 $@
!#
// Say hello to the first argument
println("Hello, " + args(0) + "!")

The initial #!/bin/sh must be the very first line in the file. Once youset its execute permission:

>chmod +x helloarg

You can run the Scala script as ashell script by simply saying:

>./helloarg globe

Which should yield:

Hello, globe!

Step 6. Loop with while, decidewith if

You write while loops in Scala in much the same way you do inJava. Try out a while by typing the following intoa file name printargs.scala:

var i = 0
while (i < args.length) {
  println(args(i))
  i += 1
}

This script starts with a variabledefinition, var i = 0. Type inference gives i the type scala.Int, because that is the type of its initial value, 0. The while constructon the next line causes the block (the code between the curly braces) to berepeatedly executed until the boolean expression i < args.length is false. args.length gives the length of the args array, similar to the way you get the length of anarray in Java. The block contains two statements, each indented two spaces, therecommended indentation style for Scala. The first statement, println(args(i)), prints out the ith command line argument. The second statement, i += 1, increments i byone. Note that Java’s ++i and i++ don’t work in Scala. To increment in Scala, youneed to say either i = i + 1 or i += 1. Run this script with the following command:

>scala printargs.scala Scala is fun

And you should see:

Scala
is
fun

For even more fun, type thefollowing code into a new file named echoargs.scala:

var i = 0
while (i < args.length) {
  if (i != 0)
    print(" ")
  print(args(i))
  i += 1
}
println()

In this version, you’ve replacedthe println call with a print call, so that all the arguments will be printedout on the same line. To make this readable, you’ve inserted a single spacebefore each argument except the first via the if (i != 0) construct. Since i != 0 will be false thefirst time through the while loop, no space will getprinted before the initial argument. Lastly, you’ve added one more println to the end, to get a line return after printingout all the arguments. Your output will be very pretty indeed.

If you run this script with thefollowing command:

>scala echoargs.scala Scala is even more fun

You’ll get:

Scala is even more fun

Note that in Scala, as in Java, youmust put the boolean expression for a while oran if in parentheses. (In other words, you can’t say inScala things like if i <10 as you can in a language suchas Ruby. You must say if (i <10) in Scala.) Another similarityto Java is that if a block has only one statement, you can optionally leave offthe curly braces, as demonstrated by the if statementin echoargs.scala. And although you haven’t seen many of them, Scala doesuse semi-colons to separate statements as in Java, except that in Scala thesemi-colons are very often optional, giving some welcome relief to your rightpinky finger. If you had been in a more verbose mood, therefore, you could havewritten theechoargs.scala script as follows:

var i = 0;
while (i < args.length) {
  if (i != 0) {
    print(" ");
  }
  print(args(i));
  i += 1;
}
println();

If you type the previous code intoa new file named echoargsverbosely.scala, and run it with the command:

> scala echoargsverbosely.scala In Scala semicolons are often optional

You should see the output:

In Scala semicolons are often optional

Note that because you had noparameters to pass to the println method, you could have leftoff the parentheses and the compiler would have been perfectly happy. But giventhe style guideline that you should always use parentheses when calling methodsthat may have side effects—coupled with the fact that by printing to thestandard output, println will indeed have sideeffects—you specified the parentheses even in the concise echoargs.scala version.

One of the benefits of Scala thatyou can begin to see with these examples, is that Scala gives you theconciseness of a scripting language such as Ruby or Python, but withoutrequiring you to give up the static type checking of more verbose languageslike Java or C++. Scala’s conciseness comes not only from its ability to inferboth types and semicolons, but also its support for the functional programmingstyle, which is discussed in the next step.

Step 7. Iterate with foreach and for

Although you may not have realizedit, when you wrote the while loops in the previous step, you were programmingin an imperative style. In the imperative style, which isthe style you would ordinarily use with languages like Java, C++, and C, yougive one imperative command at a time, iterate with loops, and often mutatestate shared between different functions or methods. Scala enables you to programimperatively, but as you get to know Scala better, you’ll likely often findyourself programming in a more functional style. In fact, oneof the main aims of the Scalazine will be to help you become as competent atfunctional programming as you are at imperative programming, using Scala as avehicle.

One of the main characteristics ofa functional language is that functions are first class constructs, and that’svery true in Scala. For example, another (far more concise) way to print eachcommand line argument is:

args.foreach(arg => println(arg))

In this code, you call the foreach method on args,and pass in a function. In this case, you’re passing in an anonymousfunction (one with no name), which takes one parameternamed arg. The code of the anonymousfunction isprintln(arg). If you type the above code into anew file named pa.scala, and execute with the command:

scala pa.scala Concise is nice

You should see:

Concise
is
nice

In the previous example, the Scalainterpreter infers type of arg to be String, since Stringsare what the array on which you’re calling foreach is holding. If you’d prefer to be more explicit, you canmention the type name, but when you do you’ll need to wrap the argument portionin parentheses (which is the normal form of the syntax anyway). Try typing thisinto a file named epa.scala.

args.foreach((arg: String) => println(arg))

Running this script has the samebehavior as the previous one. With the command:

scala epa.scala Explicit can be nice too

You’ll get:

Explicit
can
be
nice
too

If instead of an explicit mood,you’re in the mood for even more conciseness, you can take advantage of aspecial case in Scala. If an anonymous function consists of one methodapplication that takes a single argument, you need not explicitly name andspecify the argument. Thus, the following code also works:

args.foreach(println)

To summarize, the syntax for ananonymous function is a list of named parameters, in parentheses, a rightarrow, and then the body of the function. This syntax is illustrated in Figure1.

 

Figure 1. The syntax of a Scala anonymous function.

 

Now, by this point you may bewondering what happened to those trusty for loops you have been accustomed tousing in imperative languages such as Java. In an effort to guide you in afunctional direction, only a functional relative of the imperative for (called a for comprehension) is available inScala. While you won’t see their full power and expressiveness in this article,we will give you a glimpse. In a new file named forprintargs.scala, type the following:

for (arg <- args)
  println(arg)

The parentheses after the for in this for comprehension contain arg <- args. To the left of the <- symbol,which you can say as “in”, is a declaration of a new \@val@ (not a \@var@)named arg. To the right of <- is the familiar argsarray. When this code executes, arg will be assigned to each element of the args array and the body of the for, println(arg), will be executed. Scala’s for comprehensions can domuch more than this, but this simple form is similar in functionality to Java5′s:

// ...
for (String arg : args) {     // Remember, this is Java, not Scala
    System.out.println(arg);
}
// ...

or Ruby’s

for arg in ARGV   # Remember, this is Ruby, not Scala
  puts arg
end

When you run the forprintargs.scala script with the command:

scala forprintargs.scala for is functional

You should see:

for
is
functional

Step 8. Parameterize Arrays with types

In addition to being functional,Scala is object-oriented. In Scala, as in Java, you define a blueprint forobjects with classes. From a class blueprint, you can instantiate objects, orclass instances, by using new. For example, the following Scalacode instantiates a new String and prints it out:

val s = new String("Hello, world!")
println(s)

In the previous example, you parameterize the String instance with the initial value "Hello, world!". You can think of parameterizationas meaning configuring an instance at the point in your program that you createthat instance. You configure an instance with values by passing objects to aconstructor of the instance in parentheses, just like you do when you create aninstance in Java. If you place the previous code in a new file named paramwithvalues.scala and run it with scala paramswithvalues.scala, you’ll see the familiar Hello, world! greeting printed out.

In addition to parameterizinginstances with values at the point of instantiation, you can in Scala alsoparameterize them with types. This kind of parameterization is akin tospecifying a type in angle brackets when instantiating a generic type in Java 5and beyond. The main difference is that instead of the angle brackets used forthis purpose in Java, in Scala you use square brackets. Here’s an example:

val greetStrings = new Array[String](3)
 
greetStrings(0) = "Hello"
greetStrings(1) = ", "
greetStrings(2) = "world!\n"
 
for (i <- 0 to 2)
  print(greetStrings(i))

In this example, greetStrings is a value of type Array[String] (say this as, “an array of string”) that isinitialized to length 3 by passing the value 3 to a constructor in parentheses in the first lineof code. Type this code into a new file called paramwithtypes.scala and execute it with scala paramwithtypes.scala, and you’ll see yet another Hello, world! greeting. Note that when you parameterize aninstance with both a type and a value, the type comes first in its squarebrackets, followed by the value in parentheses.

Had you been in a more explicitmood, you could have specified the type of greetStrings explicitly like this:

val greetStrings: Array[String] = new Array[String](3)
// ...

Given Scala’s type inference, thisline of code is semantically equivalent to the actual first line of codein paramwithtypes.scala. But this form demonstrates thatwhile the type parameterization portion (the type names in square brackets)form part of the type of the instance, the value parameterization part (thevalues in parentheses) do not. The type of greetStrings is Array[String], not Array[String](3).

The next three lines of codein paramwithtypes.scala initializes each element ofthe greetStrings array:

// ...
greetStrings(0) = "Hello"
greetStrings(1) = ", "
greetStrings(2) = "world!\n"
// ...

As mentioned previously, arrays inScala are accessed by placing the index inside parentheses, not square bracketsas in Java. Thus the zeroeth element of the array is greetStrings(0), not greetStrings[0] as in Java.

These three lines of codeillustrate an important concept to understand about Scala concerning themeaning of val. When you define a variablewith val, the variable can’t be reassigned,but the object to which it refers could potentially still be mutated. So inthis case, you couldn’t reassign greetStrings to a different array; greetStrings will always point to the same Array[String] instance with which it was initialized. Butyou can change the elements of thatArray[String] over time, so the array itself is mutable.

The final two lines in paramwithtypes.scala contain a for comprehensionthat prints out each greetStrings array element in turn.

// ...
for (i <- 0 to 2)
  print(greetStrings(i))

The first line of code in this forcomprehension illustrates another general rule of Scala: if a method takes onlyone parameter, you can call it without a dot or parentheses. to is actually a method that takes one Int argument. The code 0 to 2 is transformed into the method call 0.to(2). (This to methodactually returns not an Array but a Scala iterator thatreturns the values 0, 1, and 2.) Scala doesn’t technically have operatoroverloading, because it doesn’t actually have operators in the traditionalsense. Characters such as +-*, and /, have no special meaning in Scala, but they can be usedin method names. Thus, the expression 1 + 2,which was the first Scala code you typed into the interpreter in Step 1, isessential in meaning to 1.+(2), where + is the name of a method defined in class scala.Int.

Another important idea illustratedby this example will give you insight into why arrays are accessed withparentheses in Scala. Scala has fewer special cases than Java. Arrays aresimply instances of classes like any other class in Scala. When you applyparentheses to a variable and pass in some arguments, Scala will transform thatinto an invocation of a method named apply.So greetStrings(i) gets transformed into greetStrings.apply(i). Thus accessing the element of anarray in Scala is simply a method call like any other method call. What’s more,the compiler will transform any application of parentheseswith some arguments on any type into an apply method call, not just arrays. Ofcourse it will compile only if that type actually defines an apply method. So it’s not a special case; it’s a generalrule.

Similarly, when an assignment ismade to a variable that is followed by some arguments in parentheses, thecompiler will transform that into an invocation of an update method that takes two parameters. For example,

greetStrings(0) = "Hello"

will essentially be transformedinto

greetStrings.update(0, "Hello")

Thus, the following Scala code issemantically equivalent to the code you typed into paramwithtypes.scala:

val greetStrings = new Array[String](3)
 
greetStrings.update(0, "Hello")
greetStrings.update(1, ", ")
greetStrings.update(2, "world!\n")
 
for (i <- 0.to(2))
  print(greetStrings.apply(i))

Scala achieves a conceptualsimplicity by treating everything, from arrays to expressions, as objects withmethods. You as the programmer don’t have to remember lots of special cases,such as the differences in Java between primitive and their correspondingwrapper types, or between arrays and regular objects. However, it issignificant to note that in Scala this uniformity does not usually come with aperformance cost as it often has in other languages that have aimed to be purein their object orientation. The Scala compiler uses Java arrays, primitivetypes, and native arithmetic where possible in the compiled code. Thus Scalareally does give you the best of both worlds in this sense: the conceptualsimplicity of a pure object-oriented language with the runtime performancecharacteristics of language that has special cases for performance reasons.

Step 9. Use Lists and Tuples

One of the big ideas of thefunctional style of programming is that methods should not have side effects.The only effect of a method should be to compute the value or values that arereturned by the method. Some benefits gained when you take this approach arethat methods become less entangled, and therefore more reliable and reusable.Another benefit of the functional style in a statically typed language is thateverything that goes into and out of a method is checked by a type checker, sologic errors are more likely to manifest themselves as type errors. To applythis functional philosophy to the world of objects, you would make objectsimmutable. A simple example of an immutable object in Java is String. If you create a String withthe value "Hello,", it will keep that value for therest of its lifetime. If you later call concat("world!") on that String,it will not add "world!" to itself. Instead, it willcreate and return a brand new String withthe value Hello,world!".

As you’ve seen, a Scala Array is a mutable sequence of objects that all sharethe same type. An Array[String] contains only Strings, for example. Although you can’t change the length ofan Array after it is instantiated, you can change itselement values. Thus, Arrays are mutable objects. Animmutable, and therefore more functional-oriented, sequence of objects thatshare the same type is Scala’s List.As with Arrays, a List[String] contains only Strings.Scala’sListscala.List, differs from Java’s java.util.List type in that Scala Lists are always immutable (whereas Java Lists can be mutable). But more importantly, Scala’s List is designed to enable a functional style ofprogramming. Creating a List is easy, you just say:

val oneTwoThree = List(1, 2, 3)

This establishes a new \@val@named oneTwoThree, which initialized with anew List[Int] with the integer elementvalues 1, 2 and 3. (You don’t need to say new List because “List” is defined as a factory method onthe scala.Listsingleton object. More on Scala’s singleton objectconstruct in Step 11.) Because Listsare immutable, they behave a bit like Java Stringsin that when you call a method on one that might seem by its name to implythe List will be mutated, it insteadcreates a new List with the new value andreturns it. For example, List has a method named ::: that concatenates a passed List and the List onwhich ::: was invoked. Here’s how youuse it:

val oneTwo = List(1, 2)
val threeFour = List(3, 4)
val oneTwoThreeFour = oneTwo ::: threeFour
println(oneTwo + " and " + threeFour + " were not mutated.")
println("Thus, " + oneTwoThreeFour + " is a new List.")

Type this code into a new filecalled listcat.scala and execute it with scala listcat.scala, and you should see:

List(1, 2) and List(3, 4) were not mutated.
Thus, List(1, 2, 3, 4) is a new List.

Enough said.2

Perhaps the most common operatoryou’ll use with Lists is ::, which is pronounced “cons.” Cons prepends a newelement to the beginning of an existing List,and returns the resulting List. For example, if you type thefollowing code into a file named consit.scala:

val twoThree = List(2, 3)
val oneTwoThree = 1 :: twoThree
println(oneTwoThree)

And execute it with scala consit.scala, you should see:

List(1, 2, 3)

Given that a shorthand way tospecify an empty List is Nil, one way to initialize new Lists is to string together elements with the cons operator,with Nil as the last element. Forexample, if you type the following code into a file namedconsinit.scala:

val oneTwoThree = 1 :: 2 :: 3 :: Nil
println(oneTwoThree)

And execute it with scala consinit.scala, you should again see:

List(1, 2, 3)

Scala’s List is packed with useful methods, many of which areshown in Table 1.

 

What it Is

What it Does

List()

Creates an empty List

Nil

Creates an empty List

List("Cool", "tools", "rule")

Creates a new List[String] with the three values "Cool""tools", and "rule"

val thrill = "Will" :: "fill" :: "until" :: Nil

Creates a new List[String] with the three values "Will""fill", and "until"

thrill(2)

Returns the 2nd element (zero based) of the thrill List (returns "until")

thrill.count(s => s.length == 4)

Counts the number of String elements in thrill that have length 4 (returns 2)

thrill.drop(2)

Returns the thrill List without its first 2 elements (returns List("until"))

thrill.dropRight(2)

Returns the thrill List without its rightmost 2 elements (returns List("Will"))

thrill.exists(s => s == "until")

Determines whether a String element exists in thrill that has the value "until" (returns true)

thrill.filter(s => s.length == 4)

Returns a List of all elements, in order, of the thrill List that have length 4 (returns List("Will", "fill"))

thrill.forall(s => s.endsWith("l"))

Indicates whether all elements in the thrill List end with the letter "l" (returns true)

thrill.foreach(s => print(s))

Executes the print statement on each of the Strings in the thrill List (prints "Willfilluntil")

thrill.foreach(print)

Same as the previous, but more concise (also prints "Willfilluntil")

thrill.head

Returns the first element in the thrill List (returns "Will")

thrill.init

Returns a List of all but the last element in the thrill List (returns List("Will", "fill"))

thrill.isEmpty

Indicates whether the thrill List is empty (returns false)

thrill.last

Returns the last element in the thrill List (returns "until")

thrill.length

Returns the number of elements in the thrill List (returns 3)

thrill.map(s => s + "y")

Returns a List resulting from adding a "y" to each String element in the thrill List (returns List("Willy", "filly", "untily"))

thrill.remove(s => s.length == 4)

Returns a List of all elements, in order, of the thrill List except those that have length 4 (returns List("until"))

thrill.reverse

Returns a List containing all element of the thrill List in reverse order (returns List("until", "fill", "Will"))

thrill.sort((s, t) => s.charAt(0).toLowerCase < t.charAt(0).toLowerCase)

Returns a List containing all element of the thrill List in alphabetical order of the first character lowercased (returns List("fill", "until", "Will"))

thrill.tail

Returns the thrill List minus its first element (returns List("fill", "until"))

 

Table 1. Some List methods and usages.

Besides List, one otherordered collection of object elements that’s very useful in Scala is the tuple. Like Lists, tuples areimmutable, but unlike Lists, tuples can contain different types of elements. Thuswhereas a list might be aList[Int] or a List[String], a tuple could contain both an Int and a String at the sametime. Tuples are very useful, for example, if you need to return multipleobjects from a method. Whereas in Java, you would often create a JavaBean-likeclass to hold the multiple return values, in Scala you can simply return atuple. And it is simple: to instantiate a new tuple that holds some objects,just place the objects in parentheses, separated by commas. Once you have atuple instantiated, you can access its elements individually with a dot,underscore, and the one-based index of the element. For example, type thefollowing code into a file named luftballons.scala:

val pair = (99, "Luftballons")
println(pair._1)
println(pair._2)

In the first line of this code, youcreate a new tuple that contains an Int withthe value 99 as its first element, and a String withthe value "Luftballons" as its second element. Scalainfers the type of the tuple to be Tuple2[Int, String], and gives that type to the variable pair as well. In the second line, you access the _1 field, which will produce the first element, 99.The . in the second line is thesame dot you’d use to access a field or invoke a method. In this case you areaccessing a field named _1. If you run this script with scala luftballons.scala, you’ll see:

99
Luftballons

The actual type of a tuple dependsupon the number and of elements it contains and the types of those elements.Thus, the type of (99,"Luftballons") is Tuple2[Int, String]. The type of ('u', 'r', "the", 1, 4,"me") isTuple6[Char, Char, String, Int, Int, String].

Step 10. Use Sets and Maps

Because Scala aims to help you takeadvantage of both functional and imperative styles, its collections librariesmake a point to differentiate between mutable and immutable collection classes.For example, Arrays are always mutable, whereas Lists are always immutable. When it comes to Sets and Maps,Scala also provides mutable and immutable alternatives, but in a different way.For Sets and Maps, Scala models mutability in the class hierarchy.

For example, the Scala API containsa base trait for Sets,where a trait is similar to a Java interface. (You’ll find out more about traitsin Step 12.) Scala then provides two subtraits, one for mutable Sets, and another for immutableSets. As you can see in Figure 2, these three traits allshare the same simple name, Set.Their fully qualified names differ, however, because they each reside in a differentpackage. Concrete Set classes in the Scala API,such as theHashSet classes shown in Figure 2,extend either the mutable or immutable Set trait.(Although in Java you implement interfaces, in Scala you “extend” traits.) Thus, if you want to use a HashSet, you can choose between mutable and immutable varietiesdepending upon your needs.

 

Figure 2. Class hierarchy for Scala Sets.

 

To try out Scala Sets, type the following code into a file named jetset.scala:

import scala.collection.mutable.HashSet
 
val jetSet = new HashSet[String]
jetSet += "Lear"
jetSet += ("Boeing", "Airbus")
println(jetSet.contains("Cessna"))

The first line of jetSet.scala imports the mutable HashSet. As with Java, the import allows you to use the simplename of the class, HashSet, in this source file. After ablank line, the third line initializes jetSet witha new HashSet that will contain only Strings. Note that just as with Lists and Arrays,when you create a Set, you need to parameterize it witha type (in this case, String), since every object in a Set must share the same type. The subsequent two linesadd three objects to the mutable Set viathe += method. As with most othersymbols you’ve seen that look like operators in Scala, += is actually a method defined on class HashSet. Had you wanted to, instead of writing jetSet += "Lear", you could have written jetSet.+=("Lear"). Because the += method takes a variable number of arguments, youcan pass one or more objects at a time to it. For example, jetSet += "Lear" adds one String to the HashSet, but jetSet +=("Boeing", "Airbus") adds two Strings to the set. Finally, the last line prints out whether or notthe Set contains a particular String. (As you’d expect, it prints false.)

Another useful collection class inScala is Maps. As with Sets, Scala provides mutable and immutable versionsof Map, using a class hierarchy. As you can see in Figure 3,the class hierarchy for Maps looks a lot like the onefor Sets. There’s a base Map trait in package scala.collection, and two subtrait Maps: a mutable Map in scala.collection.mutable and an immutable one in scala.collection.immutable.

 

Figure 3. Class hierarchy for Scala Maps.

 

Implementations of Map, such as the HashMaps shown in the class hierarchy in Figure 3, implement either themutable or immutable trait. To see a Map inaction, type the following code into a file named treasure.scala.

// In treasure.scala
 
import scala.collection.mutable.HashMap
 
val treasureMap = new HashMap[Int, String]
treasureMap += 1 -> "Go to island."
treasureMap += 2 -> "Find big X on ground."
treasureMap += 3 -> "Dig."
println(treasureMap(2))

On the first line of treasure.scala, you import the mutable form of HashMap. After a blank line, you define a val named treasureMap and initialize it with a new mutable HashMap whose keys will be Ints and values Strings.On the next three lines you add key/value pairs to the HashMap using the -> method.As illustrated in previous examples, the Scala compiler transforms an binaryoperation expression like 1 ->"Go to island." into 1.->("Go to island."). Thus, when you say 1 -> "Go to island.", you are actually calling a methodnamed -> on an Int with the value 1, and passing in a String with the value "Go to island." This -> method,which you can invoke on any object in a Scala program3, returns a two-element tuple containing the key andvalue. You then pass this tuple to the += methodof the HashMap object to which treasureMap refers. Finally, the last line prints the valuethat corresponds to the key 2 inthetreasureMap. If you run this code, it will print:

Find big X on ground.

Because maps are such a usefulprogramming construct, Scala provides a factory method for Maps that is similar in spirit to the factory method shownin Step 9 that allows you to create Listswithout using the new keyword. To try out this moreconcise way of constructing maps, type the following code into a filecalled numerals.scala:

// In numerals.scala
val romanNumeral = Map(1 -> "I", 2 -> "II", 3 -> "III", 4 -> "IV", 5 -> "V")
println(romanNumeral(4))

In numerals.scala you take advantage of the fact that the theimmutable Map trait is automaticallyimported into any Scala source file. Thus when you say Map in the first line of code, the Scala interpreterknows you meanscala.collection.immutable.Map. In this line, you call a factorymethod on the immutable Map‘s companion object5, passing in five key/value tuples as parameters. Thisfactory method returns an instance of the immutable HashMapcontaining the passed key/value pairs. The name of thefactory method is actually apply, but as mentioned in Step 8, ifyou say Map(...) it will be transformed by thecompiler to Map.apply(...). If you run the numerals.scala script, it will print IV.

Step 11. Understand classes and singleton objects

Up to this point you’ve writtenScala scripts to try out the concepts presented in this article. For all butthe simplest projects, however, you will likely want to partition yourapplication code into classes. To give this a try, type the following code intoa file called greetSimply.scala:

// In greetSimply.scala
 
class SimpleGreeter {
  val greeting = "Hello, world!"
  def greet() = println(greeting)
}
 
val g = new SimpleGreeter
g.greet()

greetSimply.scala is actually a Scala script,but one that contains a class definition. This first, example, however,illustrates that as in Java, classes in Scala encapsulate fields and methods.Fields are defined with either val or var. Methods are defined with def. For example, in class SimpleGreetergreeting is a field and greet is a method. To use the class, you initializea val named g witha new instance of SimpleGreeter. You then invoke the greet instance method on g. If you run this script with scala greetSimply.scala, you will be dazzled with yetanother Hello, world!.

Although classes in Scala are inmany ways similar to Java, in several ways they are quite different. Onedifference between Java and Scala involves constructors. In Java, classes haveconstructors, which can take parameters, whereas in Scala, classes can takeparameters directly. The Scala notation is more concise—class parameters can beused directly in the body of the class; there’s no need to define fields andwrite assignments that copy constructor parameters into fields. This can yieldsubstantial savings in boilerplate code; especially for small classes. To seethis in action, type the following code into a file named greetFancily.scala:

// In greetFancily.scala
 
class FancyGreeter(greeting: String) {
  def greet() = println(greeting)
}
 
val g = new FancyGreeter("Salutations, world")
g.greet

Instead of defining a constructorthat takes a String, as you would do in Java, in greetFancily.scala you placed the greeting parameter of that constructor in parenthesesplaced directly after the name of the class itself, before the open curly braceof the body of class FancyGreeter. When defined in this way, greeting essentially becomes a value (not a variable—itcan’t be reassigned) field that’s available anywhere inside the body. In fact,you pass it to println in the body of the greet method. If you run this script with thecommand scala greetFancily.scala, it will inspire you with:

Salutations, world!

This is cool and concise, but whatif you wanted to check the String passed to FancyGreeter‘s primary constructor for null, and throw NullPointerException to abort the construction of the new instance?Fortunately, you can. Any code sitting inside the curly braces surrounding theclass definition, but which isn’t part of a method definition, is compiled intothe body of the primary constructor. In essence, the primary constructor willfirst initialize what is essentially a final field for each parameter inparentheses following the class name. It will then execute any top-level codecontained in the class’s body. For example, to check a passed parameter for null, type in the following code into a file namedgreetCarefully.scala:

// In greetCarefully.scala
class CarefulGreeter(greeting: String) {
 
  if (greeting == null) {
    throw new NullPointerException("greeting was null")
  }
 
  def greet() = println(greeting)
}
 
new CarefulGreeter(null)

In greetCarefully.scala, an if statement is sitting smack in the middle of theclass body, something that wouldn’t compile in Java. The Scala compiler placesthis if statement into the body ofthe primary constructor, just after code that initializes what is essentially afinal field named greeting with the passed value. Thus,if you pass in null to the primary constructor,as you do in the last line of the greetCarefully.scala script, the primary constructor will firstinitialize the greeting field to null. Then, it will execute the if statement that checks whether the greeting field is equal to null, and since it is, it will throw a NullPointerException. If you run greetCarefully.scala, you will see aNullPointerException stack trace.

In Java, you sometimes give classesmultiple constructors with overloaded parameter lists. You can do that in Scalaas well, however you must pick one of them to be the primary constructor, andplace those constructor parameters directly after the class name. You thenplace any additional auxiliary constructors in thebody of the class as methods named this.To try this out, type the following code into a file named greetRepeatedly.scala:

// In greetRepeatedly.scala
class RepeatGreeter(greeting: String, count: Int) {
 
  def this(greeting: String) = this(greeting, 1)
 
  def greet() = {
    for (i <- 1 to count)
      println(greeting)
  }
}
 
val g1 = new RepeatGreeter("Hello, world", 3)
g1.greet()
val g2 = new RepeatGreeter("Hi there!")
g2.greet()

RepeatGreeter‘s primary constructor takes not only a String greeting parameter, but also an Int count of the number of times to print thegreeting. However, RepeatGreeter also contains a definition ofan auxiliary constructor, thethis method that takes asingle String greeting parameter. The body of this constructor consistsof a single statement: an invocation of the primary constructor parameterizedwith the passed greeting and a count of 1. In thefinal four lines of the greetRepeatedly.scala script, you create two RepeatGreeters instances, one using each constructor, and call greet on each. If you run greetRepeatedly.scala, it will print:

Hello, world
Hello, world
Hello, world
Hi there!

Another area in which Scala departsfrom Java is that you can’t have any static fields or methods in a Scala class.Instead, Scala allows you to create singleton objects using thekeyword object. A singleton object cannot, andneed not, be instantiated with new.It is essentially automatically instantiated the first time it is used, and asthe “singleton” in its name implies, there is ever only one instance. Asingleton object can share the same name with a class, and when it does, thesingleton is called the class’s companion object. The Scalacompiler transforms the fields and methods of a singleton object to staticfields and methods of the resulting binary Java class. To give this a try, typethe following code into a file named WorldlyGreeter.scala:

// In WorldlyGreeter.scala
 
// The WorldlyGreeter class
class WorldlyGreeter(greeting: String) {
  def greet() = {
    val worldlyGreeting = WorldlyGreeter.worldify(greeting)
    println(worldlyGreeting)
  }
}
 
// The WorldlyGreeter companion object
object WorldlyGreeter {
  def worldify(s: String) = s + ", world!"
}

In this file, you define both aclass, with the class keyword, and a companionobject, with the object keyword. Both types arenamed WorldlyGreeter. One way to think about this ifyou are coming from a Java programming perspective is that any static methodsthat you would have placed in class WorldlyGreeter in Java, you’d put in singleton object WorldlyGreeter in Scala. In fact, when the Scala compilergenerates bytecodes for this file, it will create a Java class named WorldlyGreeter that has an instance method named greet (defined in the WorldlyGreeter class in the Scala source) and a static methodnamed worldify (defined in the WorldlyGreeter companion object in Scala source). Note also thatin the first line of the greet method in class WorldlyGreeter, you invoke the singleton object’s worldify method using a syntax similar to the way youinvoke static methods in Java: the singleton object name, a dot, and the methodname:

// Invoking a method on a singleton object from class WorldlyGreeter 
// ...
val worldlyGreeting = WorldlyGreeter.worldify(greeting)
// ...

To run this code, you’ll need tocreate an application. Type the following code into a file named WorldlyApp.scala:

// In WorldlyApp.scala
// A singleton object with a main method that allows
// this singleton object to be run as an application
object WorldlyApp {
  def main(args: Array[String]) {
    val wg = new WorldlyGreeter("Hello")
    wg.greet()
  }
}

Because there’s no classnamed WorldlyApp, this singleton object is not acompanion object. It is instead called a stand-alone.object. Thus, a singleton object is either a companion or a stand-alone object.The distinction is important because companion objects get a few specialprivileges, such as access to private members of the like-named class.

One difference between Scala andJava is that whereas Java requires you to put a public class in a file namedafter the class—for example, you’d put class SpeedRacer in file SpeedRacer.java—in Scala, you can name .scala files anything you want, no matter what Scalaclasses or code you put in them. In general in the case of non-scripts,however, it is recommended style to name files after the classes they containas is done in Java, so that programmers can more easily locate classes by lookingat file names. This is the approach we’ve taken with the two files in thisexample, WorldlyGreeter.scala and WorldlyApp.scala.

Neither WorldlyGreeter.scala nor WorldlyApp.scala are scripts, because they endin a definition. A script, by contrast, must end in a result expression. Thusif you try to run either of these files as a script, for example by typing:

scala WorldlyGreeter.scala # This won't work!

The Scala interpreter will complainthat WorldlyGreeter.scala does not end in a resultexpression. Instead, you’ll need to actually compile these files with the Scalacompiler, then run the resulting class files. One way to do this is to usescalac, which is the basic Scala compiler. Simply type:

scalac WorldlyApp.scala WorldlyGreeter.scala

Given that the scalac compiler starts up a new JVM instance each time itis invoked, and that the JVM often has a perceptible start-up delay, the Scaladistribution also includes a Scala compiler daemon called fsc (for fast Scala compiler). You use it like this:

fsc WorldlyApp.scala WorldlyGreeter.scala

The first time you run fsc, it will create a local server daemon attached to aport on your computer. It will then send the list of files to compile to thedaemon via the port, and the daemon will compile the files. The next time yourun fsc, the daemon will already berunning, so fsc will simply send the filelist to the daemon, which will immediately compile the files. Using fsc, you only need to wait for the the JVM to startup the firsttime. If you ever want to stop the fsc daemon,you can do so with fsc-shutdown.

Running either of these scalac or fsc commandswill produce Java class files that you can then run via the scala command, the same command you used to invoke theinterpreter in previous examples. However, instead of giving it a filename witha .scala extension containing Scala code to interpret6 as you did in every previous example, in this caseyou’ll give it the name of a class containing a main method. Similar to Java, any Scala class witha main method that takes a single parameter of type Array[String] and returns Unit7 can serve as the entry point to an application. Inthis example, WorldlyApp has a main method with the proper signature, so you can runthis example by typing:

scala WorldlyApp

At which point you should see:

Hello, world!

You may recall seeing this outputpreviously, but this time it was generated in this interesting manner:

·     The scala program fires up a JVM withthe WorldlyApp‘s main methodas the entry point.

·     WordlyApp‘s main methodcreates a new WordlyGreeter instance via new, passing in the string "Hello" as a parameter.

·     Class WorldlyGreeter‘s primary constructor essentiallyinitializes a final field named greeting with the passed value, "Hello" (this initialization code isautomatically generated by the Scala compiler).

·     WordlyApp‘s main methodinitializes a local \@val@ named wg with the new WorldlyGreeter instance.

·     WordlyApp‘s main methodthen invokes greet onthe WorldlyGreeter instance to which wg refers.

·     Class WordlyGreeter‘s greet method invokes worldify on singleton object WorldlyGreeter, passing along the value of thefinal field greeting"Hello".

·     Companionobject WorldlyGreeter‘s worldify method returns a String consisting of the value of a concatenation ofthe s parameter,which is "Hello", and the literal String ", world!".

·     Class WorldlyGreeter‘s greet method then initializes a\@val@ named worldlyGreetingwithplaces the "Hello, world!" String returned from the worldify method.

·     Class WorldlyGreeter‘s greet method passes the "Hello,world!" String to which worldlyGreeting refers to println, which sends the cheerfulgreeting, via the standard output stream, to you.

Step 12. Understand traits and mixins

As first mentioned in Step 10,Scala includes a construct called a trait, which is similar in spirit toJava’s interface. One main difference betweenJava interfaces and Scala’s traits are thatwhereas all methods in Java interfaces are by definition abstract, you can give methods real bodieswith real code in Scala traits. Here’s an example:

trait Friendly {
  def greet() = "Hi"
}

In this example, the greet method returns the String "Hi". If you are coming from Java,this greet method may look a littlefunny to you, as if greet() is somehow a field beinginitialized to the String value "Hi". What is actually going on is that lacking anexplicit return statement, Scala methods willreturn the value of the last expression. In this case, the value of the lastexpression is "Hi", so that is returned. A moreverbose way to say the same thing would be:

trait Friendly {
  def greet(): String = {
    return "Hi"
  }
}

Regardless of how your write themethods, however, the key point is that Scala traits can actually containnon-abstract methods. Another difference between Java interfaces and Scala traits is that whereas you implement Javainterfaces, you extend Scala traits. Otherthan this implements/extends difference, however, inheritance when you are defining a newtype works in Scala similarly to Java. In both Java and Scala, a class can extendone (and only one) other class. In Java, an interface can extend zero to many interfaces. Similarly in Scala, a trait can extend zero to many traits. InJava, a class can implement zero to many interfaces. Similarly in Scala, a class can extend zeroto many traits.implements is not a keyword in Scala.

Here’s an example:

class Dog extends Friendly {
  override def greet() = "Woof"
}

In this example, class Dog extends trait Friendly. This inheritance relationship implies much the same thingas interface implementation does in Java. You can assigna Dog instance to a variable of type Friendly. For example:

var pet: Friendly = new Dog
println(pet.greet())

When you invoke the greet method on the Friendly pet variable, it will use dynamicbinding, as in Java, to determine which implementation of the method to call.In this case, class Dog overrides the greet method, so Dog‘simplementation of greet will be invoked. Were you toexecute the above code, you would get Woof (Dog‘s implementation of greet),not Hi (Friendly‘s implementation of greet).Note that one difference with Java is that to override a method in Scala, youmust precede the method’s def with override. If you attempt to override a method withoutspecifying override, your Scala code won’t compile.

Finally, one quite significantdifference between Java’s interfaces and Scala’s traits is that inScala, you can mix in traits at instantiation time. For example, consider thefollowing trait:

trait ExclamatoryGreeter extends Friendly {
  override def greet() = super.greet() + "!"
}

Trait ExclamatoryGreeter extends trait Friendly and overrides the greet method. ExclamatoryGreeter‘s greet method first invokes thesuperclass’s greet method, appends anexclamation point to whatever the superclass’sgreet methodreturns, and returns the resulting String.With this trait, you can mix in its behavior atinstantiation time using the with keyword.Here’s an example:

val pup: Friendly = new Dog with ExclamatoryGreeter
println(pup.greet())

Given the initial line of code, theScala compiler will create a synthetic8 type that extends class Dog and trait ExclamatoryGreeter and instantiate it. When you invoke a method onthe synthetic type, it will cause the correct implementation to be invoked.When you run this code, the pup variablewill first be initialized with the new instance of the synthetic type, thenwhen greet is invoked on pup, you’ll see "Woof!". Note that had pup notbeen explicitly defined to be of typeFriendly, the Scala compiler would have inferred the type of pup to be Dog with ExclamatoryGreeter.

To give all these concepts a try,type the following code into a file named friendly.scala:

trait Friendly {
  def greet() = "Hi"
}
 
class Dog extends Friendly {
  override def greet() = "Woof"
}
 
class HungryCat extends Friendly {
  override def greet() = "Meow"
}
 
class HungryDog extends Dog {
  override def greet() = "I'd like to eat my own dog food"
}
 
trait ExclamatoryGreeter extends Friendly {
  override def greet() = super.greet() + "!"
}
 
var pet: Friendly = new Dog
println(pet.greet())
 
pet = new HungryCat
println(pet.greet())
 
pet = new HungryDog
println(pet.greet())
 
pet = new Dog with ExclamatoryGreeter
println(pet.greet())
 
pet = new HungryCat with ExclamatoryGreeter
println(pet.greet())
 
pet = new HungryDog with ExclamatoryGreeter
println(pet.greet())

When you run the friendly.scala script, it will print:

Woof
Meow
I'd like to eat my own dog food
Woof!
Meow!
I'd like to eat my own dog food!

Conclusion

As you may have glimpsed by readingthis article, the promise of Scala is that you can get more productivity whileleveraging existing investments. Scala’s basic conciseness of syntax andsupport for the functional programming style promise increased programmerproductivity compared to the Java langauge, while enabling you to continue totake advantage of all the great things about the Java platform. You cancomplement Java code with Scala code and continue to leverage your existingJava code and APIs, the many APIs available for the Java platform, the runtimeperformance offered by JVMs, and your own knowledge of the Java platform.

With the knowledge you’ve gained inthis article, you should already be able to get started using Scala for smalltasks, especially scripts. In future articles, we will dive into more detail inthese topics, and introduce other topics that weren’t even hinted at here.

Share your opinion

Have a question or opinion aboutScala? Discuss this article in the Articles Forum topic, First Steps to Scala.

End notes

1. A method is recursive if itcalls itself.

2. Actually, the veryattentive reader may have noticed something amiss with the associativity ofthe ::: method, but it is actually asimple rule to remember. If a method is used as an operator, as in a * b or a ::: b, the method is invoked on the left hand operand, as in a.*(b), unless the method name ends in a colon. If the methodname ends in a colon, then the method is invoked on the right hand operand, asin b.:::(a).

3. The Scala mechanism thatallows you to invoke -> on any object is called implicitconversion, which will be covered in a future article.

4. A method has sideeffects if it changes state outside the method.

5. Companion objects will becovered in Step 11.

6. The actual mechanism thatthe scala program uses to “interpret” aScala source file is that it compiles the Scala source code to bytecodes inmemory, loads them immediately via a class loader, and executes them.

7. As mentioned in Step2, Unit in Scala is similar to void in Java. Whereas in Java, a main method must return void, in Scala, it must return Unit.

8. A synthetic typeis generated automatically by the compiler rather than being written by hand bythe programmer.

Resources

The Scala programming language homepage is at:
http://www.scala-lang.org/

The Scala mailing list:
http://listes.epfl.ch/cgi-bin/doc_en?liste=scala

The Scala wiki:
http://scala.sygneca.com/

A Scala plug-in for Eclipse:
http://www.scala-lang.org/downloads/eclipse/index.html

A Scala plug-in for IntelliJ:
http://plugins.intellij.net/plugin/?id=1347

The lift Web Framework runs insidea Java web container and uses Scala for coding:
http://liftweb.net/

About the authors

Bill Venners is president ofArtima, Inc., which publishes the Artima Developer website at www.artima.com.He is author of the book, Inside the Java Virtual Machine, a programmer-orientedsurvey of the Java platform’s architecture and internals. His popular columnsin JavaWorld magazine covered Java internals, object-oriented design, and Jini.Bill has been active in the Jini Community since its inception. He led the JiniCommunity’s ServiceUI project, whose ServiceUI API became the de facto standardway to associate user interfaces to Jini services. Bill also serves as anelected member of the Jini Community’s initial Technical Oversight Committee(TOC), and in this role helped to define the governance process for thecommunity.

Martin Odersky is the creator ofthe Scala language. As a professor at EPFL in Lausanne, Switzerland he isworking on programming languages, more specifically languages forobject-oriented and functional programming. His research thesis is that the twoparadigms are two sides of the same coin, to be identified as much as possible.To prove this, he has experimented with a number of language designs, fromPizza to GJ to Functional Nets. He has also influenced the development of Javaas a co-designer of Java generics and as the original author of the currentjavac reference compiler. Since 2001 he has concentrated on designing,implementing, and refining the Scala programming language.Lex Spoon divides histime between working at EPFL in Switzerland and at IBM Research in New YorkState. He holds a Ph.D. from Georgia Tech. He is interested in programminglanguage design and implementation, with special focus on packaging, pluggabletypes, and static analysis for optimization, safe software evolution, andverification of domain-specific properties.

云帆教育大数据学院www.cloudyhadoop.com

通过最新实战课程,系统学习hadoop2.x开发技能,在云帆教育,课程源于企业真实需求,最有实战价值,成为正式会员,可无限制在线学习全部教程;培训市场这么乱,云帆大数据值得你选择!!详情请加入QQ:374152400 ,咨询课程顾问!

关注云帆教育微信公众号yfteach,第一时间获取公开课信息。

0 0
原创粉丝点击