Today’s enterprise and Internet applications must balance a number of concerns. They must be implemented quickly and reliably. New features must be added in short, incremental cycles. Beyond simply providing business logic, applications must support secure access, persistence of data, transactional behavior, and other advanced features. Applications must be highly available and scalable, requiring designs that support concurrency and distribution. Applications are networked and provide interfaces for both people and other applications to use.
To meet these challenges, many developers are looking for new languages and tools. Venerable standbys like Java, C#, and C++ are no longer optimal for developing the next generation of applications.
C# venerable? Please qualify... Given the evolution of C# language from 1.0 - next major version 4.0, not to mention enhancements to the class library and the CLR, it is not clear to me how C# can be viewed as venerable...
It's true that Microsoft has kept C# moving forward at a faster rate than Java. However, It is still based on design choices that I think are sub-optimal, like not using type inferencing from the very beginning. C# won't be able to move to more comprehensive type inferencing than it supports now because of the potential parsing ambiguities its syntax would cause.
as I understand it, the significant advantage that Erlang and Scala offer over Java and C#, for example, are concurrent programming for use in multi-core envmts. And Scala is even more attractive in a J2SE or J2EE platform because it runs in a JVM (compiles to Java bytecode).
Microsoft .NET has just recently implemented the MVC design pattern in ASP.NET:
http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx
In many ways, .NET is far behind but traction in JEE frameworks other than Spring and Hibnerate (e.g. Seam 2.x) is very low and EE 6 with Web Beans may not have a high adoption rate in the enterprise deployments either...
Java was officially introduced by Sun Microsystems in May of 1995, at the advent of widespread interest in the Internet. Java was immediately hailed as an ideal language for writing browser-based applets, where a secure, portable, and developer-friendly application language was needed. The reigning language of the day, C++, was not suitable for this domain.
Today, Java is more often used for server-side applications. It is one of the most popular languages in use for the development of web and enterprise applications.
However, Java was a child of its time. Now it shows its age. In 1995, Java provided a syntax similar enough to C++ to entice C++ developers, while avoiding many of that language’s deficiencies and “sharp edges”. Java adopted the most useful ideas for the development problems of its era, such as object-oriented programming (OOP), while discarding more troublesome techniques, such as manual memory management. These design choices struck an excellent balance that minimized complexity and maximized developer productivity, while trading-off performance compared to natively-compiled code. While Java has evolved since its birth, many people believe it has grown too complex without adequately addressing some newer development challenges.
It seems a little bit strange to describe garbage collection as 'discarding more troublesome techniques such as manual memory management'. Maybe you could name garbage collection directly as one of the useful ideas that Java adopted.
Java solved many plumbing problems related with C++ programming such as static and dynamic memory management. Also, Java developers had a more legible, well looked sintaxis. So we can say that Java is a cleaner version of C++.
-- this is based on Andrew Troelsen's book: http://books.google.com/books?id=VGT1_UJzjM0C&pg=PA1371&dq=.NET+Apress#PPA7,M1
oops. Page 8: http://books.google.com/books?id=VGT1_UJzjM0C&pg=PA1371&dq=.NET+Apress#PPA8,M1
Yea, our intention isn't to provide a detailed comparison between C++ and Java, but just to indicate the sea change Java represented at the time and to argue that we need another sea change now.
Developers want languages that are more succinct and flexible to improve their productivity. This is one reason why so-called “scripting” languages like Ruby and Python have become more popular recently.
I'd say that not only Ruby has become more popular, but also Python and Clojure, another new popular language for the JVM.
Will make this statement more 'inclusive".
what about Groovy? we can use Groovy in Seam apps...
"I can honestly say if someone had shown me the Programming Scala book by by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have never created Groovy."
http://java.dzone.com/articles/scala-long-term-replacement
The never-ending need to scale is driving architectures towards pervasive concurrency. However, Java’s concurrency model, which is based on synchronized access to shared, mutable state, results in complex and error-prone programs.
Scala is OO based which is almost inherently embraces mutability. This is a long way from Clojure's approach. Actors model is sufficient only for a limited segment of problems.
I think we'll see clojure style mutability approaches, like STM, work their way back into Scala and maybe even Java, as options.
Just a comment on the writing, this line is difficult to understand
The never-ending need to scale is driving architectures towards pervasive concurrency.
I think you meant the following The never-ending need to scale "software" is driving "application" architectures towards pervasive concurrency.
and I would rather like The never-ending need to scale software is driving application developers towards concurrent architectures.
scale Hardware/Software? architectures Hardware/Software/
Am I to read the original line as
The never-ending need to scale software is driving software architectures towards pervasive concurrency.
The never-ending need to scale software is driving hardware architectures towards pervasive concurrency.
The never-ending need to scale hardware is driving hardware architectures towards pervasive concurrency.
or one of the alternatives
While the Java language is showing its age, the Java Virtual Machine (JVM) on which it runs continues to shine. The optimizations performed by today’s JVM are extraordinary, allowing byte code to outperform natively-compiled code in many cases. Today, many developers believe that using the JVM with new languages is the path forward. Sun is embracing this trend by employing many of the lead developers of JRuby and Jython, which are JVM ports of Ruby and Python, respectively.
The appeal of Scala for the Java developer is that it gives you a newer, more modern language, while leveraging the JVM’s amazing performance and the wealth of Java libraries that have been developed for over a decade.
Dynamically typed languages like Ruby, Python, Groovy, JavaScript, and Smalltalk offer very high productivity due to their flexibility, powerful metaprogramming, and elegance.
Despite their productivity advantages, dynamic languages may not be the best choices for all applications, particularly for very large code bases and high-performance applications. There is a longstanding, spirited debate in the programming community about the relative merits of dynamic vs. static typing. Many of the points of comparison are somewhat subjective. We won’t go through all the arguments here, but we will offer a few thoughts for consideration.
I'd say that static typing isn't only about what types variables have, but also what types expressions have.
Given the headings, a Java programmer may skip this section thinking that it is not relevant to them. If they do, they will miss the whole Static vs Dynamic discussion.
Optimizing the performance of a dynamic language is more challenging than for a static language. In a static language, optimizers can exploit the type information to make decisions. In a dynamic language, fewer such clues are available for the optimizer, making optimization choices harder. While recent advancements in optimizations for dynamic languages are promising, they lag behind the state of the art for static languages. So, if you require very high performance, static languages are probably a safer choice.
Static languages can also benefit the development process. IDE features like autocompletion (sometimes called code sense) are easier to implement for static languages, again because of the extra type information available. The more explicit type information in static code promotes better “self-documentation”, which can be important for communicating intent among developers, especially as a project grows.
When using a static language, you have to think about appropriate type choices more often, which forces you to weigh design choices more carefully. While this may slow down daily design decisions, thinking through the types in the application can result in a more coherent design over time.
As you mentioned previously pro and cons of static and dynamic typing are subjective, but this paragraph is a flame bait
"forces you to weigh design choices more carefully."
Caring about your craft forces you to weigh design choices more carefully and lead to coherent design over time.
I have seen plenty of code in Java that returns Object and invokes methods using reflection over the returned typed. What was needed was an interface that all the returned types returned. Static typing does not by itself lead to better design.
Another small benefit of static languages is the extra checking the compiler performs. We think this advantage is often oversold, as type mismatch errors are a small fraction of the runtime errors you typically see. The compiler can’t find logic errors, which are far more significant. Only a comprehensive, automated test suite can find logic errors. For dynamically typed languages, the tests must cover possible type errors, too. If you are coming from a dynamically typed language, you may find that your test suites are a little smaller, as a result, but not that much smaller.
Many developers who find static languages too verbose often blame static typing for the verbosity when the real problem is a lack of type inference. In type inference, the compiler infers the types of values based on the context. For example, the compiler will recognize that x = 1 + 3
means that x
must be an integer. Type inference reduces verbosity significantly, making the code feel more like code written in a dynamic language.
We have worked with both static and dynamic languages, at various times. We find both kinds of languages compelling for different reasons. We believe the modern software developer must master a range of languages and tools. Sometimes, a dynamic language will be the right tool for the job. At other times, a static language like Scala is just what you need.
This paragraph could be made much concise without losing meaning.
Scala is a language that addresses the major needs of the modern developer. It is a statically typed, mixed-paradigm, JVM language with a succinct, elegant, and flexible syntax, a sophisticated type system, and idioms that promote scalability from small, interpreted scripts to large, sophisticated applications. That’s a mouthful, so let’s look at each of those ideas in more detail.
As we described in the previous section, a statically typed language binds the type to a variable for the lifetime of that variable. In contrast dynamically typed languages bind the type to the actual value referenced by a variable, meaning that the type of a variable can change along with the value it references.
Of the set of newer JVM languages, Scala is one of the few that is statically typed and it is the best known among them.
Statically typed languages also bind a type to every value (or object). Otherwise, polymorphism through dynamic binding would not be possible.
Surprised you did no mention type inference here (or any of the sub-sections below). Isn't Scala also one of the few "type-inferenced" languages on the JVM?
Scala fully supports Object Oriented Programming (OOP). Scala improves upon Java’s support for OOP with the addition of traits, a clean way of implementing classes using mixin composition. Scala’s traits work much like Ruby’s modules. If you’re a Java programmer, think of traits as unifying interfaces with their implementations.
In Scala, everything is really an object. Scala does not have primitive types, like Java. Instead all numeric types are true objects. However, for optimal performance, Scala uses the underlying primitives types of the runtime whenever possible. Also, Scala does not support “static” or class-level members of types, since they are not associated with an actual instance. Instead, Scala supports a singleton object construct to support those cases where exactly one instance of a type is needed.
As a Java programmer, I don't find the idea of unifying interfaces with implementations to be an illuminating metaphor. It just makes traits sound like classes. Mixin is a clearer term, as is the reference to Ruby modules.
Scala fully supports Functional Programming (FP). FP is a programming paradigm that is older than OOP, but it has been sheltered in the ivory towers of academia until recently. Interest in FP is increasing because of the ways it simplifies certain design problems, especially concurrency. “Pure” functional languages don’t allow for any mutable state, thereby avoiding the need for synchronization on shared access to mutable state. Instead, programs written in pure functional languages communicate by passing messages between concurrent, autonomous processes. Scala supports this model with its Actors library, but it allows for both mutable and immutable variables.
Functions are “first-class” citizens in FP, meaning they can be assigned to variables, passed to other functions, etc., just like other values. This feature promotes composition of advanced behavior using primitive operations. Because Scala adheres to the dictum that everything is an object, functions are themselves objects in Scala.
Scala also offers closures, a feature that dynamic languages like Python and Ruby have adopted from the functional programming world, and one sadly absent from recent versions of Java. Closures are functions that reference variables from the scope enclosing the function definition. That is, the variables aren’t passed in as arguments or defined as local variables within the function. A closure "closes around" these references, so the function invocation can safely refer to the variables even when the variables have gone out of scope! Closures are such a powerful abstraction that object systems and fundamental control structures are often implemented using them.
While Scala is primarily known as a JVM language, meaning that Scala generates JVM byte code, a .NET version of Scala is also under development that generates CLR byte code. When we refer to the underlying “runtime”, we will usually discuss the JVM, but most of what we will say applies equally to both runtimes. When we discuss JVM-specific details, they generalize to the .NET version, except where noted.
The Scala compiler uses clever techniques to map Scala extensions to valid byte-code idioms. From Scala, you can easily invoke byte code that originated as Java source (for the JVM) or C# source (for .NET). Conversely, you can invoke Scala code from Java, C#, etc.. Running on the JVM and CLR allows the Scala developer to leverage available libraries and to interoperate with other languages hosted on those runtimes.
Java syntax can be verbose. Scala uses a number of techniques to minimize unnecessary syntax, making Scala code as succinct as code in most dynamically typed languages. Type inference minimizes the need for explicit type information in many contexts. Declarations of types and functions are very concise.
Scala allows function names to include non-alphanumeric characters. Combined with some syntactic sugar, this feature permits the user to define methods that look and behave like operators. As a result, libraries outside the core of the language can feel “native” to users.
Scala is designed to scale from small, interpreted scripts to large, distributed applications. Scala provides four language mechanisms that promote scalable composition of systems: 1) explicit selftypes, 2) abstract type members and generics, 3) nested classes, and 4) mixin composition using traits.
No other language provides all these mechanisms. Together, they allow applications to be constructed from reusable “components” in a type-safe and succinct manner. As we will see, many common design patterns and architectural techniques like dependency injection are easy to implement in Scala without the boilerplate code or lengthy XML configuration files that can make Java development tedious.
It might appear that OOP and FP are incompatible. In fact, a design philosophy of Scala is that OOP and FP are more synergistic than opposed. The features of one approach can enhance the other.
You could elaborate about the OOP bits a litte bit more, since it is most likely the thing that Scala beginners coming from most other languages are most familiar with. You could for example say that there are no primitive types which makes the OOP types integrate better into the code freeing the programmer from bothering with this (or just say "everything is an object" which is more relevant to OOP than FP).
"Of the set of newer JVM languages, Scala is the only one that is statically typed."
With the exceptions of CAL and JavaFX.
Can you really trust Scala's speed, for example: http://villane.wordpress.com/2008/02/13/scala-for-avs-while-update/
I think there is some other issues like reflection based implementation on structural types, boxed primitives are not well optimized (afaik).
It's unfortunate thing, but you just can't blindly depend that compiler optimizes things to Java-speed; you have to code Java-like.
@Marek. Good point. We cover this later in the book, but I'll add a paragraph about it here.
@Ricky, I'll clarify to say one of the "few"...
@Henrik, I'll add a disclaimer that there can be areas where performance is poor.
In FP, functions have no side effects and variables are immutable, while in OOP, mutable state and side effects are common, even encouraged. Scala lets you choose the approach that best fits your design problems. Functional programming is especially useful for concurrency, since it eliminates the need to synchronize access to mutable state. However, “pure” FP can be restrictive. Some design problems are easier to solve with mutable objects.
The name Scala is a contraction of the words scalable language. While this suggests that the pronunciation should be scale-ah, the creators of Scala actually pronounce it scah-lah, like the Italian word for “stairs”. That is, the two “a’s” are pronounced the same.
Don't quite know where to put this comment, but would be nice to see mention of where a scalable language fits within a cloud filled internet. I like things to scale (duhhh) and it may be worthwhile to include how scala could fit within an ASP cloud model of deployment.
Not sure where to discuss it either. I guess the "default" answer is that Scala fills the same niche as Java, C#, etc. while perhaps also covering some territory for which a "pure" scripting language like Ruby would be an optimal fit.
Scala was started by Martin Odersky in 2001. Martin is a professor in the School of Computer and Communication Sciences at the Ecole Polytechnique Fédérale de Lausanne (EPFL). He spent his graduate years working in the group headed by Niklaus Wirth, of Pascal fame. Martin worked on Pizza, an early functional language on the JVM. He later worked on GJ, a prototype of what later became Generics in Java, with Philip Wadler of Haskell fame. Martin was hired by Sun Microsystems to produce the reference implementation of javac
, the Java compiler that ships with the Java Developer Kit (JDK) today.
Favour active over passive voice: change "Scala was started by Martin Odersky in 2001" to "Martin Odersky started Scala in 2001".
Martin Odersky’s background and experience are evident in the language. As you learn Scala, you come to understand that it is the product of carefully considered design decisions, exploiting the state of the art in type theory, OOP and FP. Martin’s experience with the JVM is evident in Scala’s elegant integration with that platform. The synthesis it creates between OOP and FP is an excellent "best of both worlds" solution.
Today, our industry is fortunate to have a wide variety of language options. The power, flexibility, and elegance of dynamically typed languages have made them very popular again. Yet, the wealth of Java and .NET libraries and the performance of the JVM and CLR meet many practical needs for enterprise and Internet projects.
Scala is compelling because it feels like a dynamically typed scripting language, due to its succinct syntax and type inference. Yet, Scala gives you all the benefits of static typing, a modern object model, functional programming, and an advanced type system. These tools let you build scalable, modular applications that can reuse legacy Java and .NET APIs and leverage the performance of the JVM and CLR.
Scala's syntax is not particularly succinct, even for statically typed language, compare it to Haskell, or ML based languages.
Scala is succinct relative to Java. Which ML languages run on the JVM? Is Clojure, a LISP dialect for the JVM, more concise than Scala?
Scala is a language for professional developers. Compared to languages like Java and Ruby, Scala is a more difficult language to master, because it requires competency with OOP, FP, and static typing to use it most effectively. It is tempting to prefer the relative simplicity of dynamically-typed languages. Yet, this simplicity can be deceptive. In a dynamically typed language, it is often necessary to use metaprogramming features to implement advanced designs. While metaprogramming is powerful, using it well takes experience and the resulting code tends to be hard to understand, maintain, and debug. In Scala, many of the same design goals can be achieved in a type-safe manner by exploiting its type system and mixin composition through traits.
Don't you have kind of a contradiction there: "Scala is more difficult to master" and "While metaprogramming is powerful, using it well takes experience, etc"
What does mastering really mean anyway. To get the same thing done in Scala or Ruby can be as hard if done properly (with good maintainability etc), or do you disagree?
Both Scala and metaprogramming like in Ruby take time to master. Assuming equal teams of "experts", I'm asserting that Scala code will be easier to maintain and evolve over the long-term than roughly-equivalent ruby metaprogramming code. That's my gut feeling...
I might tone this down a bit ... I mean comparatively speaking, C++, Java, Ruby, et al (statically typed languages) all require competency in OOP, FP and static typing that you indicate for Scala. As Henrik said, what does "mastering" really mean? I can point to "experienced" developers (name the language) that still write horrible code.
Put a different way: how do you measure the level of difficulty of a programming language and how this may translate to programmer productivity or suitability to solve particular problems? Experience? Empirical evidence? Anecdotal evidence? Programmer surveys? Programming language popularity?
Unfortunately, programming language choice seems largely driven by familiarity, popularity, and perceived ease of learning rather than by suitability to task and longer term program maintainability.
We feel that the extra effort required day to day to use Scala will promote more careful reflection about your designs. Over time, this discipline will yield more coherent, modular, and maintainable applications. Fortunately, you don’t need all of the sophistication of Scala all of the time. Much of your code will have the simplicity and clarity of code written in your favorite dynamically-typed language.
Ah, by "extra effort" do you mean proper design to begin with?
An alternative strategy is to combine several, simpler languages, e.g., Java for object-oriented code and Erlang for functional, concurrent code. Such a decomposition can work, but only if your system decomposes cleanly into such discrete parts and your team can manage a heterogeneous environment. Scala is attractive for situations where a single, all-in-one language is preferred. That said, Scala code can happily coexist with other languages, especially on the JVM or .NET.
You may want to point out that using Java and Erlang for the same project is most likely a poor alternative to using Java and/or Scala on their own. E.g. how would a Java class/component call an Erlang method (i.e. integration issues)?
This is the advantage of using Groovy or Scala (or other JVM-compatible languages) for integration with existing JEE or .NET systems.
To get up and running as quickly as possible, this section describes how to install the command line tools for Scala, which are all you need to work with the examples in the book. For details on using Scala in various editors and IDEs, see Integration with IDEs in Chapter 14, Scala Tools, Libraries and IDE Support. The examples used in this book were written and compiled using Scala version 2.7.5.final, the latest release at the time of this writing, and “nightly builds” of Scala version 2.8.0, which may be finalized by the time you read this.
Version 2.8 introduces many new features, which we will highlight throughout the book.
We will work with the JVM version of Scala in this book. First, you must have Java 1.4 or greater installed (1.5 or greater is recommended). If you need to install Java, go to http://www.java.com/en/download/manual.jsp and follow the instructions to install Java on your machine.
The official Scala web site is http://www.scala-lang.org/. To install Scala, go to the downloads page, http://www.scala-lang.org/downloads. Download the installer for your environment and follow the instructions on the downloads page.
The easiest cross-platform installer is the IzPack installer. Download the Scala jar file, either scala-2.7.5.final-installer.jar
or scala-2.8.0.N-installer.jar
, where N
is the latest release of the 2.8.0 version. Go to the download directory in a terminal window, and install Scala with the java
command. Assuming you downloaded scala-2.8.0.final-installer.jar
, run the following command, which will guide you through the process.
java -jar scala-2.8.0.final-installer.jar
On Mac OS X, the easiest route to a working Scala installation is via MacPorts. Follow the installation instructions at http://www.macports.org/, then sudo port install scala
. You’ll be up and running in a few minutes.
Throughout this book, we will use the symbol scala-home
to refer to the “root” directory of your Scala installation.
On Unix, Linux, and Mac OS X systems, you will need to run this command as the root
user or using the sudo
command if you want to install Scala under a system directory, e.g., scala-home
= /usr/local/scala-2.8.0.final
.
As an alternative, you can download and expand the compressed tar file (e.g., scala-2.8.0.final.tgz
) or zip file (scala-2.8.0.final.zip
). On Unix-like systems, expand the compressed file into a location of your choosing. Afterwards, add the scala-home
/bin
subdirectory in the new directory to your PATH
. For example, if you installed into /usr/local/scala-2.8.0.final
, then add /usr/local/scala-2.8.0.final/bin
to your PATH
.
To test your installation, run the following command on a command line.
scala -version
We’ll learn more about the scala
command-line tool later. You should get something like the following output:
Scala code runner version 2.8.0.final -- Copyright 2002-2009, LAMP/EPFL
Of course, the version number you see will be different if you installed a different release. From now on, when we show command output that contains the version number, we’ll show it as version 2.8.0.final
.
Congratulations, you have installed Scala! If you get an error message along the lines of scala: command not found
, make sure your environment’s PATH
is set properly to include the correct bin
directory.
Scala versions 2.7.X and earlier are compatible with JDK 1.4 and later. Scala version 2.8 drops 1.4 compatibility. Note that Scala uses many JDK classes as its own, for example, the String
class. On .NET, Scala uses the corresponding .NET classes.
You can also find downloads for the API documentation and the sources for Scala itself on the same downloads page.
As you explore Scala, you will find other useful resources that are available on http://scala-lang.org. You will find links for development support tools and libraries, tutorials, the language specification [ScalaSpec2009], and academic papers that describe features of the language.
The documentation for the Scala tools and APIs are especially useful. You can browse the API at http://www.scala-lang.org/docu/files/api/index.html. This documentation was generated using the scaladoc
tool, analogous to Java’s javadoc
tool. See the section called “The scaladoc Command Line Tool” in Chapter 14, Scala Tools, Libraries and IDE Support for more information.
You can also download a compressed file of the API documentation for local browsing using the appropriate link on the downloads page, http://www.scala-lang.org/downloads, or you can install it with the sbaz
package tool, as follows.
sbaz install scala-devel-docs
sbaz
is installed in the same bin
directory as the scala
and scalac
command-line tools. The installed documentation also includes details on the scala tool chain (including sbaz
) and code examples. For more information on the Scala command-line tools and other resources, see Chapter 14, Scala Tools, Libraries and IDE Support.
It’s time to whet your appetite with some real Scala code. In the following examples, we’ll describe just enough of the details so you understand what’s going on. The goal is to give you a sense of what programming in Scala is like. We’ll explore the details of the features in subsequent chapters.
For our first example, you could run it one of two ways, interactively or as a “script”.
Let’s start with the interactive mode. Start the scala interpreter by typing scala
and the return key on your command line. You’ll see the following output. (Some of the version numbers may vary.)
Welcome to Scala version 2.8.0.final (Java ...). Type in expressions to have them evaluated. Type :help for more information. scala>
The last line is the prompt that is waiting for your input. The interactive mode of the scala
command is very convenient for experimentation (see the section called “The scala Command Line Tool” in Chapter 14, Scala Tools, Libraries and IDE Support for more details). An interactive interpreter like this is called a REPL: Read, Evaluate, Print, Loop.
Test
Type in the following two lines of code.
val book = "Programming Scala" println(book)
The actual input and output should look like the following.
scala> val book = "Programming Scala" book: java.lang.String = Programming Scala scala> println(book) Programming Scala scala>
The first line uses the val
keyword to declare a read-only variable named book
. Note that the output returned from the interpreter shows you the type and value of book
. This can be very handy for understanding complex declarations. The second line prints the value of book
, which is “Programming Scala”.
Experimenting with the scala
command in the interactive mode (REPL) is a great way to learn the details of Scala.
Many of the examples in this book can be executed in the interpreter like this. However, it’s often more convenient to use the second option we mentioned, writing Scala scripts in a text editor or IDE and executing them with the same scala
command. We’ll do that for most of the remaining examples in this chapter.
In your text editor of choice, save the Scala code in the following example to a file named upper1-script.scala
in a directory of your choosing.
// code-examples/IntroducingScala/upper1-script.scala class Upper { def upper(strings: String*): Seq[String] = { strings.map((s:String) => s.toUpperCase()) } } val up = new Upper Console.println(up.upper("A", "First", "Scala", "Program"))
This Scala script converts strings to upper case.
By the way, that’s a comment on the first line (with the name of the source file for the code example). Scala follows the same comment conventions as Java, C#, C++, etc. A // comment
goes to the end of a line, while a /* comment */
can cross line boundaries.
To run this script, go to a command window, change to the same directory and run the following command.
As it's one of Scala's selling points, might as well keep things as concise as possible (or at least make a note of not being so to aid with initial learning).
(s:String)
the type specification is redundant
Console.
is also redundant
Of course you point this out half a page down. Ah well. :-)
This example doesn't seem to work in the current Eclipse IDE; it's fine at the command-line, but shows that the IDE support is still suspect. :/
@Geoffrey, I didn't try it any of the IDEs. We tried to avoid any dependencies on using them.
scala upper1-script.scala
The file is interpreted, meaning it is compiled and executed in one step. You should get the following output:
Array(A, FIRST, SCALA, PROGRAM)
In this example, the upper
method in the Upper
class (no pun intended) converts the input strings to upper case and returns them in an array. The last line in the example converts four strings and prints the resulting Array.
Typo in blue box above:
"We discuss these subtleties in in ."
I don't see it, but it might have been a production error where the "Command Line Tools" link disappeared in a prior build of the book. If you are STILL seeing this, could be a browser issue. Let us know with a new comment.
Let’s examine the code in detail, so we can begin to learn Scala syntax. There are a lot of details in just six lines of code! We’ll explain the general ideas here. All the ideas used in this example will be explained more thoroughly in later sections of the book.
Is this paragraph really helpful? Of course you're going to explain the ideas contained in this first program more thoroughly later :-)
Yea, I know... Always a struggle to decide how much really needs to be said...
In the example, the Upper
class begins with the class
keyword. The class body is inside the outer most curly braces {…}
.
The upper
method definition begins on the second line with the def
keyword, followed by an argument list, the return type of the method, an equals sign ‘=’, then the method body.
The argument list in parentheses is actually a variable-length argument list of String
's, indicated by the String*
type following the colon. That is, you can pass in as many comma-separated strings as you want (including an empty list). These strings are stored in a parameter named strings
. Inside the method, strings
is actually an Array
.
When explicit type information for variables is written in the code, these type annotations follow the colon after the item name (i.e., Pascal-like syntax). Why doesn’t Scala follow Java conventions? Recall that type information is often inferred in Scala (unlike Java), meaning we don’t always show type annotations explicitly. Compared to Java’s type item
convention, the item: type
convention is easier for the compiler to analyze unambiguously when you omit the colon and the type annotation and just write item
.
The method return type appears after the argument list. In this case, the return type is Seq[String]
, where Seq
("sequence") is a particular kind of collection. It is a parameterized type (like a generic type in Java), parameterized here with String
. Note that Scala uses square brackets […]
for parameterized types, while Java uses angle brackets <…>
.
Scala allows angle brackets to be used in method names, e.g., naming a “less than” method <
is common. So, to avoid ambiguities, Scala uses square brackets instead for parameterized types. They can’t be used in method names. Allowing <
and >
in method names is why Scala doesn’t follow Java’s convention for angle brackets.
The body of the upper
method comes after the equals sign ‘=’. Why an equals sign? Why not just curly braces {…}
, like in Java? Because semicolons, function return types, method arguments lists, and even the curly braces are sometimes omitted, using an equals sign prevents several possible parsing ambiguities. Using an equals sign also reminds us that even functions are values in Scala, which is consistent with Scala’s support of functional programming, described in more detail in Chapter 8, Functional Programming in Scala.
The method body calls the map
method on the strings
array, which takes a function literal as an argument. Function literals are “anonymous” functions. They are similar to lambdas, closures, blocks, or procs in other languages. In Java, you would have to use an anonymous inner class here that implements a method defined by an interface, etc.
If you're hinting at the similarity with lambdas/blocks in Ruby, adding "closures" at this point might be helpful for readers not familiar with Ruby.
Will do. Thanks.
I understand function literals as syntactic sugar. Function literal syntax can be used to code either anonymous functions (do not capture variables in scope, as in the example here, lambdas) or closures.
This is the first time I have read function literals being directly referenced as functions (albeit anonymous).
Nitpicking may be, and I am not certain what is a better approach for someone reading on scala for the first time
In this case, we passed in the following function literal.
(s:String) => s.toUpperCase()
It takes an argument list with a single String
argument named s
. The body of the function literal is after the “arrow”, =>
. It calls toUpperCase()
on s
. The result of this call is returned by the function literal. In Scala, the last expression in a function is the return value, although you can have return
statements elsewhere, too. The return
keyword is optional here and it is rarely used, except when returning out of the middle of a block (e.g., in an if
statement).
Using the following "Note" to explaining why "return" is rarely used in scala (interfering with type inference, with an appropriate reference to the section explaining type inference) might be informative for readers only accustomed to Java
We cover this topic in the next chapter. I'd rather not go into more details (even a link...) in this cursory introduction.
I know that you don't want to add any further details into this introduction, so I'm writing this comment with that in mind. For some perspective, I'm fairly new to Scala, coming to this book after a plethora of assorted blog posts and tutorials.
As someone who is familiar with Ruby, I'm a bit more interested in why => is used rather than =, and not so much in the fact that the last value of a function is the implicit return value. I think both should be mentioned, but even after reading lots of introductory information, the =/=> distinction still confuses me. Maybe a bit less real-estate for return and a bit more to explain => quickly?
"=>" suggests a function mapping. In this case, the function maps from the set of all strings to the set of upper case strings. "=" implies that the set of all strings is equivalent to the set of upper case strings, which obviously is not true. So, I think the choice of "=>" over "=" is appropriate.
The value of the last expression is the default return value of a function. No return
is required.
So, map
passes each String
in strings
to the function literal and builds up a new collection with the results returned by the function literal.
To exercise the code, we create a new Upper
instance and assign it to a variable named up
. As in Java, C#, and similar languages, the syntax new Upper
creates a new instance. The up
variable is declared as a read-only “value” using the val
keyword.
Finally, we call the upper
method on a list of strings, and print out the result with Console.println(…)
, which is equivalent to Java’s System.out.println(…)
.
We can actually simplify our script even further. Consider this simplified version of the script.
// code-examples/IntroducingScala/upper2-script.scala object Upper { def upper(strings: String*) = strings.map(_.toUpperCase()) } println(Upper.upper("A", "First", "Scala", "Program"))
This code does exactly the same thing, but with a third fewer characters.
On the first line, Upper
is now declared as an object
, which is a singleton. We are declaring a class, but the Scala runtime will only ever create one instance of Upper
. (You can’t write new Upper
, for example.) Scala uses objects
for situations where other languages would use “class-level” members, like statics
in Java. We don’t really need more than one instance here, so a singleton is fine.
This is probably just some nitpicking, but is "declared as an object, which is a singleton class" correct? According to the Scala Reference it: "defines a single object of a new class", while a "singleton class" is a class used to implement the singleton pattern... these two concepts are of course related, but in Scala object definitions are also used as a mechanism for creating modules (which AFAIK is usually not the case when using a Singleton Pattern, which got a bad reputation in the last years).
I'll drop the word "class" from "singleton class" and maybe add some more text.
Why doesn’t Scala support statics? Since everything is an object in Scala, the object
construct keeps this policy consistent. Java’s static methods and fields are not tied to an actual instance.
Note that this code is fully thread safe. We don’t declare any variables that might cause thread-safety issues. The API methods we use are also thread-safe. Therefore, we don’t need multiple instances. A singleton object
works fine.
It's not clear at all how the example code could possibly not be thread-safe in Scala or any other language since state has not even been introduced yet.
I think the point you are trying to make is that it is a little bit tricky to implement the Singleton pattern in Java without introducing subtle concurrency problems, while in Scala you can just use an 'object' as a singleton without such concerns.
That's all I'm really saying.
Just a comment on the comment. ;)
I did not understand what was being said, until I read Bruce Leidl's comment about scala singletons not have concurrency considerations that you would have when implementing the same in Java.
The implementation of upper
on the second line is also simpler. Scala can usually infer the return type of the method (but not the types of the method arguments), so we drop the explicit declaration. Also, because there is only one expression in the method body, we drop the braces and put the entire method definition on one line. The equals sign before the method body tells the compiler, as well as the human reader, where the method body begins.
The equals sign before the method body tells the compiler, as well as the human reader, where the method body begins.
Is this redundant, and possibly misleading? You already have a must better reason for the equals sign previously when you say
"Using an equals sign also reminds us that even functions are values in Scala, which is consistent with Scala’s support of functional programming"
We have also exploited a short-hand for the function literal. Previously we wrote it as follows.
(s:String) => s.toUpperCase()
We can shorten it to the following expression.
_.toUpperCase()
Because map
takes one argument, a function, we can use the “placeholder” indicator _ instead of a named parameter. That is, the _ acts like an anonymous variable, to which each string will be assigned before toUpperCase
is called. Note that the String
type is inferred for us, too. As we will see, Scala uses _ as a “wild card” in several contexts.
You can also use this short-hand syntax in some more complex function literals, as we will see in Chapter 3, Rounding Out the Essentials.
The chapter reference is missing here (mentioning it in case you have missed it).
@Marek: This was just a bug in the rendering system that was dropping the cross reference text. It's been fixed.
On the last line, using an object
rather than a class
simplifies the code. Instead of creating an instance with new Upper
, we can just call the upper
method on the Upper
object directly (note how this looks like the syntax you would use when calling static methods in a Java class).
Adding a little note explaining that this is also the actual syntax when accessing static methods in Java libraries from Scala code would informative for Java converts or people interested in Scala because of the large number of available (Java) libraries.
Finally, Scala automatically imports many methods for I/O, like println
, so we don’t need to call Console.println()
. We can just use println
by itself. (See the section called “The Predef Object” in Chapter 7, The Scala Object System for details on the types and methods that are automatically imported or defined.)
Let’s do one last refactoring; let’s convert the script into a compiled, command-line tool.
// code-examples/IntroducingScala/upper3.scala object Upper { def main(args: Array[String]) = { args.map(_.toUpperCase()).foreach(printf("%s ",_)) println("") } }
Now the upper
method has been renamed main
. Because Upper
is an object
, this main
method works exactly like a static main
method in a Java class. It is the entry point to the Upper
application.
In the example I believe it is good scala convention to omit the '=' sign as the main method finished with a println, i.e. has result type Unit (would be the same if println was omitted as foreach has a result type of Unit)
The convention is used to indicate "procedural" (relies on side effects, printf) behavior of main
In Scala, main
must be a method in an object
. (In Java, main
must be a static
method in a class
.) The command line arguments for the application are passed to main
in an array of strings, e.g., args: Array[String]
.
The first line inside the main
method uses the same short-hand notation for map
that we just examined.
Note .. main must be a (possibly inherited) method in an object?
args.map(_.toUpperCase())...
The call to map
returns a new collection. We iterate through it with foreach
. We use a _
placeholder shortcut again in another function literal that we pass to foreach
. In this case, each string in the collection is passed as an argument to printf
.
...foreach(printf("%s ",_))
To be clear, these two uses of ‘_’ are completely independent of each other. Method chaining and function-literal shorthands, as in this example, can take some getting used to, but once you are comfortable with them, they yield very readable code with minimal use of temporary variables.
It is difficult to tell that the character before the underscore here is a comma, not a period. Perhaps it should be mentioned explicitly in the text. As well, function parameters are usually separated using a comma and a space, so the curried function here would appear better as:
printf("%s ", _)
An off-hand reference to the arguments could include the word comma to differentiate this from the _.functionName syntax above: "Here the underscore is given as the second parameter of the function, separated from the print format string by a comma, as usual."
The last line in main
adds a final linefeed to the output.
This time, you must first compile the code to a JVM .class
file using scalac
.
scalac upper3.scala
You should now have a file named Upper.class
, just as if you had just compiled a Java class.
You may have noticed that the compiler did not complain when the file was named upper3.scala
and the object
was named Upper
. Unlike Java, the file name doesn’t have to match the name of the type with public
scope. (We’ll explore the visibility rules in the section called “Visibility Rules” in Chapter 5, Basic Object-Oriented Programming in Scala.) In fact, unlike Java, you can have as many public types in a single file as you want. Furthermore, the directory location of a file doesn’t have to match the package declaration. However, you can certainly follow the Java conventions, if you want to.
Now, you can execute this command for any list of strings. Here is an example.
scala -cp . Upper Hello World!
The -cp .
option adds the current directory to the search “class path”. You should get the following output.
Typo above. Should read ... adds the current directory...
Thanks! Will fix
HELLO WORLD!
Therefore, we have met the requirement a programming language book must start with a “hello world” program.
There are many reasons to be seduced by Scala. One reason is the Actors
API included in the Scala library, which is based on the robust Actors
concurrency model built into Erlang [Haller2007]. Here is an example to whet your appetite.
In Erlang, there is no "Actors" library -- the concurrency in Erlang is part of the language.
"built-in Actors library" reads a bit like as if Actors were part of the Scala Language definition; a stronger hint, that Actors in Scala are "just" a library would IMHO be good. Together with Steven's comment above, maybe: "One reason is Scala's Actors library, a concurrency API based on the Erlang's Actors concurrency model." ... removed "robust" due to the "New Lift Actor code" Mail by David Pollak in the Lift Google Group ... which might make a nice side note showing off Scala's flexibility :-)
Good points. Will fix.
In the Actor model of concurrency [Agha1987], independent software entities called actors share no state information with each other. Instead, they communicate by exchanging messages. By eliminating the need to synchronize access to shared, mutable state, it is far easier to write robust, concurrent applications.
In this example, instances in a geometric Shape
hierarchy are sent to an actor for drawing on a display. Imagine a scenario where a rendering “farm” generates scenes in an animation. As the rendering of a scene is completed, the shape “primitives” that are part of the scene are sent to an actor for a display subsystem.
To begin, we define a Shape
class hierarchy.
// code-examples/IntroducingScala/shapes.scala package shapes { class Point(val x: Double, val y: Double) { override def toString() = "Point(" + x + "," + y + ")" } abstract class Shape() { def draw(): Unit } class Circle(val center: Point, val radius: Double) extends Shape { def draw() = println("Circle.draw: " + this) override def toString() = "Circle(" + center + "," + radius + ")" } class Rectangle(val lowerLeft: Point, val height: Double, val width: Double) extends Shape { def draw() = println("Rectangle.draw: " + this) override def toString() = "Rectangle(" + lowerLeft + "," + height + "," + width + ")" } class Triangle(val point1: Point, val point2: Point, val point3: Point) extends Shape { def draw() = println("Triangle.draw: " + this) override def toString() = "Triangle(" + point1 + "," + point2 + "," + point3 + ")" } }
The Shape
class hierarchy is defined in a shapes
package. You can declare the package using Java syntax, but Scala also supports a syntax similar to C#'s “namespace” syntax, where the entire declaration is scoped using curly braces, as used here. The Java-style package declaration syntax is far more commonly used, however, being both compact and readable.
Circle and Rectangle extend Shape, but Triangle extends Shape(). If this wasn't intentional, it might confuse readers.
Good catch. Thanks. Will fix.
Thought I would add that up until this point in the samples, it is possible to use the Scala REPL, which I find convenient. However with the introduction of packages it would not be possible to use the REPL as the REPL does not support packages. Might be worth noting for readers like me who type packages in the REPL.
The Point
class represents a two-dimensional point on a plane. Note the argument list after the class name. Those are constructor parameters. In Scala, the whole class body is the constructor, so you list the arguments for the primary constructor after the class name and before the class body. (We’ll see how to define auxiliary constructors in the section called “Constructors in Scala” in Chapter 5, Basic Object-Oriented Programming in Scala.) Because we put the val
keyword before each parameter declaration, they are automatically converted to read-only fields with the same names with public reader methods of the same name. That is, when you instantiate a Point
instance, e.g., point
, you can read the fields using point.x
and point.y
. If you want mutable fields, then use the keyword var
. We’ll explore variable declarations and the val
and var
keywords in the section called “Variable Declarations” in Chapter 2, Type Less, Do More.
Typo: "auxiliary constructors in in "
Another production problem that has since been fixed. Sorry.
The body of Point
defines one method, an override of the familiar toString
method in Java (like ToString
in C#). Note that Scala, like C#, requires the override
keyword whenever you override a concrete method. Unlike C#, you don’t have to use a virtual
keyword on the original concrete method. In fact, there is no virtual
keyword in Scala. As before, we omit the curly braces "{…}" around the body of toString
, since it has only one expression.
Not certain about this, however I also omit the () braces around methods with no args along with the {} braces as it enforces the uniform access principle in Scala. Clients of the code do not need to know that they are invoking a function or accessing a member
override def toString() = "Point(" + x + "," + y + ")"
would becode
override def toString = "Point(" + x + "," + y + ")"
not certain about its applicability to methods defined in the Java API being overridden in Scala.
Shape
is an abstract class. Abstract classes in Scala are similar to those in Java and C#. We can’t instantiate instances of abstract classes, even when all their field and method members are concrete.
In this case, Shape declares an abstract draw
method. We know it is abstract because it has no body. No abstract
keyword is required on the method. Abstract methods in Scala are just like abstract methods in Java and C#. (See the section called “Overriding Members of Classes and Traits” in Chapter 6, Advanced Object-Oriented Programming In Scala for more details.)
Maybe a quick explanation of "Unit" here?
Thanks. Oversight. Will fix.
The draw
method returns Unit
, which is a type that is roughly equivalent to void
in C-derived languages like Java, etc. (See the section called “The Scala Type Hierarchy” in Chapter 7, The Scala Object System for more details.)
Circle
is declared as a concrete subclass of Shape
. It defines the draw
method to simply print a message to the console. Circle
also overrides toString
.
Rectangle
is also a concrete subclass of Shape
that defines draw
and overrides toString
. For simplicity, we assume it is not rotated relative to the X and Y axes. Hence, all we need is one point, the lower left-hand point will do, and the height and width of the rectangle.
we assume it is not rotated relative to the X and Y axes
Ehh??? Do not understand what is being said and am not certain it needs to be said.
Triangle
follows the same pattern. It takes three Points
as its constructor arguments.
Both draw
methods in Circle
, Rectangle
, and Triangle
use this
. As in Java and C#, this
is how an instance refers to itself. In this context, where this
is the right-hand side of a String concatenation expression (using the plus sign), this.toString
is invoked implicitly.
Of course, in a real application, you would not implement drawing in “domain model” classes like this, since the implementations would depend on details like the operating system platform, graphics API, etc. We will see a better design approach when we discuss traits in Chapter 4, Traits.
Now that we have defined our shapes types, let’s return to actors. We define an Actor
that receives “messages” that are shapes to draw.
In "Of course, in a real..." you're talking down to your readers. There's no need for that, certainly at the start of the book. Just drop the "Of course".
Not my intention. Rather I was talking "up" to them, because most experienced devs. would implement this separation of concerns and I want them to know we'll learn techniques for doing that later on.
since the implementations would depend on details like the operating system platform, graphics API
not when running on the JVM. I agree that draw should not be in the domain model classes for the reason in your comment above "separation of concerns" not for the reasons in the Notes section.
OS is a concern that is abstracted away by the virtual machine
// code-examples/IntroducingScala/shapes-actor.scala package shapes { import scala.actors._ import scala.actors.Actor._ object ShapeDrawingActor extends Actor { def act() { loop { receive { case s: Shape => s.draw() case "exit" => println("exiting..."); exit case x: Any => println("Error: Unknown message! " + x) } } } } }
The actor is declared to be part of the shapes
package. Next, we have two import statements.
ShapeDrawingActor is also defined as a singleton (object). Assume that is necessary, but why?
ShapeDrawingActor is also defined as a singleton (object). Assume that is necessary, but why?
The first import statement imports all the types in the scala.actors
package. In Scala, the underscore _ is used the way the star * is used in Java.
Because * is a valid character for a function name, it can’t be used as the import
wild card. Instead, _ is reserved for this purpose.
All the methods and public fields from Actor
are imported. These are not static
imports from the Actor
type, as they would be in Java. Rather, they are imported from an object
that is also named Actor
. The class
and object
can have the same name, as we will see in the section called “Companion Objects” in Chapter 6, Advanced Object-Oriented Programming In Scala.
Typo last sentence: as we will see in ...
Missing links now fixed.
Our actor class definition, ShapeDrawingActor
, is an object
that extends Actor
(the type, not the object
). The act
method is overridden to do the unique work of the actor. Because act
is an abstract method, we don’t need to explicitly override it with the override
keyword. Our actor loops indefinitely, waiting for incoming messages.
During each pass in the loop, the receive
method is called. It blocks until a new message arrives. Why is the code after receive
enclosed in curly braces ({…}
) and not parentheses ((…)
)? We will learn later that there are cases where this substitution is allowed and it is quite useful (see Chapter 3, Rounding Out the Essentials). For now, what you need to know is that the expressions inside the braces constitute a single function literal that is passed to receive
. This function literal does a pattern match on the message instance to decide how to handle the message. Because of the case
clauses, it looks like a typical switch statement in Java, for example, and the behavior is very similar.
The first case
does a type comparison with the message. (There is no explicit variable for the message instance in the code; it is inferred.) If the message is of type Shape
, the first case
matches. The message instance is cast to a Shape
and assigned to the variable s
, then the draw
method is called on it.
A reference to a section that talks about how this inferrence works would be useful; I'm curious, but I've got no link to click.
If the message is not a Shape
, the second case
is tried. If the message is the string "exit"
, the actor prints a message and terminates execution. Actors should usually have a way to exit gracefully!
The last case
clause handles any other message instance, thereby functioning as the default case. The actor reports an error and then drops the message. Any
is the parent of all types in the Scala type hierarchy, like Object
is the root type in Java and other languages. Hence, this case clause will match any message of any type. Pattern matching is eager; we have to put this case clause at the end, so it doesn’t consume the messages we are expecting!
Don't you mean, 'if we don't want it to silently consume the messages we aren't expecting'?
Okay, no you don't mean that. But maybe you could emphasize 'at the end' a bit more, and point out that unexpected messages would still be consumed (but silently) if it wasn't included.
Recall that we declared draw
as an abstract method in Shape
and we implemented draw
in the concrete subclasses. Hence, the code in the first case
statement invokes a polymorphic operation.
Hopefully we also implemented draw in Triangle!
Thanks. We fixed that one ;)
Finally, here is a script that uses the ShapeDrawingActor
actor.
// code-examples/IntroducingScala/shapes-actor-script.scala import shapes._ ShapeDrawingActor.start() ShapeDrawingActor ! new Circle(new Point(0.0,0.0), 1.0) ShapeDrawingActor ! new Rectangle(new Point(0.0,0.0), 2, 5) ShapeDrawingActor ! new Triangle(new Point(0.0,0.0), new Point(1.0,0.0), new Point(0.0,1.0)) ShapeDrawingActor ! 3.14159 ShapeDrawingActor ! "exit"
The shapes in the shapes
package are imported.
The ShapeDrawingActor
actor is started. By default, it runs in its own thread (there are alternatives we will discuss in Chapter 9, Robust, Scalable Concurrency with Actors), waiting for messages.
Five messages are sent to the actor, using the syntax actor ! message
. The first message sends a Circle
instance. The actor “draws” the circle. The second message sends a Rectangle
message. The actor “draws” the rectangle. The third message does the same thing for a Triangle
. The fourth message sends a Double
that is approximately equal to Pi. This is an unknown message for the actor, so it just prints an error message. The final message sends an “exit” string, which causes the actor to terminate.
Typo: it says "The four message sends...", it should say "The fourth message sends...".
Thanks!
To try out the actor example, start by compiling the first two files. You can get the sources from the O’Reilly download site (see the section called “Getting the Code Examples” in the Preface for details) or you can create them yourself.
Use the following command to compile the files.
scalac shapes.scala shapes-actor.scala
While the source file names and locations don’t have to match the file contents, you will notice that the generated class files are written to a shapes
directory and there is one class file for each class we defined. The class file names and locations must conform to the JVM requirements.
Now you can run the script to see the actor in action.
scala -cp . shapes-actor-script.scala
You should see the following output.
Circle.draw: Circle(Point(0.0,0.0),1.0) Rectangle.draw: Rectangle(Point(0.0,0.0),2.0,5.0) Triangle.draw: Triangle(Point(0.0,0.0),Point(1.0,0.0),Point(0.0,1.0)) Error: Unknown message! 3.14159 exiting...
For more on Actors
, see Chapter 9, Robust, Scalable Concurrency with Actors.
We made the case for Scala and got you started with two sample Scala programs, one of which gave you a taste of Scala’s Actors library for concurrency. Next, we’ll dive into more Scala syntax, emphasizing various keystroke-economical ways of getting lots of work done.
No comments yet
Add a comment