summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorschinz <schinz@epfl.ch>2003-12-04 15:28:34 +0000
committerschinz <schinz@epfl.ch>2003-12-04 15:28:34 +0000
commitdbbab2f7f8b7cd16155112068c4784809ddd73f7 (patch)
tree80d958c99d04d015b4cb4016f4bf0bbb2d5e8b3b /doc
parent3b81bb39eb779dc97fa270d62b3f339c72d9fce2 (diff)
downloadscala-dbbab2f7f8b7cd16155112068c4784809ddd73f7.tar.gz
scala-dbbab2f7f8b7cd16155112068c4784809ddd73f7.tar.bz2
scala-dbbab2f7f8b7cd16155112068c4784809ddd73f7.zip
- added sections about case classes and genericity
- fixed small problems
Diffstat (limited to 'doc')
-rw-r--r--doc/tutorial/ScalaTutorial.scala.tex492
1 files changed, 379 insertions, 113 deletions
diff --git a/doc/tutorial/ScalaTutorial.scala.tex b/doc/tutorial/ScalaTutorial.scala.tex
index 7d83406f7b..f35b4cb793 100644
--- a/doc/tutorial/ScalaTutorial.scala.tex
+++ b/doc/tutorial/ScalaTutorial.scala.tex
@@ -7,22 +7,21 @@
\usepackage{scaladoc}
\usepackage{xspace}
-\usepackage{url}
\ifpdf
\pdfinfo {
/Author (Michel Schinz)
- /Title (Scala Tutorial)
- /Keywords (Scala)
- /Subject ()
+ /Title (A Scala Tutorial)
+ /Keywords (Scala programming language tutorial)
+ /Subject (Basic introduction to Scala, mostly for Java programmers)
/Creator (TeX)
/Producer (PDFLaTeX)
}
\fi
-\renewcommand{\doctitle}{Scala Tutorial}
+\renewcommand{\doctitle}{A Scala Tutorial}
\renewcommand{\docsubtitle}{for Java programmers}
-\renewcommand{\docauthor}{Michel Schinz}
+\renewcommand{\docauthor}{Michel Schinz\\[65mm]}
\newcommand{\langname}[1]{#1\xspace}
@@ -32,10 +31,9 @@
\newcommand{\toolname}[1]{\texttt{#1}\xspace}
\newcommand{\scalac}{\toolname{scalac}}
+\newcommand{\scala}{\toolname{scala}}
\newcommand{\java}{\toolname{java}}
-\newcommand{\ident}[1]{\code{#1}\xspace}
-
\begin{document}
\makedoctitle
@@ -52,9 +50,9 @@ is assumed.
\label{sec:first-example}
As a first example, we will use the standard \emph{Hello world}
-program, which is not very fascinating but makes it easy to
-demonstrate the use of the \Scala tools without knowing too much about
-the language. Here is how it looks:
+program. It is not very fascinating but makes it easy to demonstrate
+the use of the \Scala tools without knowing too much about the
+language. Here is how it looks:
\begin{scalaprogram}{HelloWorld}
object HelloWorld {
def main(args: Array[String]): unit = {
@@ -64,24 +62,24 @@ object HelloWorld {
\end{scalaprogram}
The structure of this program should be familiar to Java programmers:
-it consists of one method called \ident{main} which takes the command
+it consists of one method called \code{main} which takes the command
line arguments, an array of strings, as parameter; the body of this
-method consists of a single call to the \ident{println} method of the
+method consists of a single call to the \code{println} method of the
object representing the standard output, with the friendly greeting as
-argument. The \ident{main} method is declared as returning a value of
-type \ident{unit}, which for now can be seen as similar to \Java's
-\ident{void} type.
+argument. The \code{main} method is declared as returning a value of
+type \code{unit}, which for now can be seen as similar to \Java's
+\code{void} type.
-What should be less familiar to Java programmers is the \ident{object}
-declaration containing the \ident{main} method. Such a declaration
+What is less familiar to Java programmers is the \code{object}
+declaration containing the \code{main} method. Such a declaration
introduces what is commonly known as a \emph{singleton object}, that
is a class with a single instance. The declaration above thus declares
-both a class called \ident{HelloWorld} and an instance of that class,
-also called \ident{HelloWorld}. This instance is created lazily, the
-first time it is used.
+both a class called \code{HelloWorld} and an instance of that class,
+also called \code{HelloWorld}. This instance is created on demand,
+the first time it is used.
-The astute reader might also have noticed that the \ident{main} method
-is not declared as \ident{static} here. This is because static members
+The astute reader might have noticed that the \code{main} method is
+not declared as \code{static} here. This is because static members
(methods or fields) do not exist in \Scala. Rather than define static
members, the \Scala programmer declares these members in singleton
objects.
@@ -95,33 +93,27 @@ maybe some options, and produces one or several object files. The
object files it produces are standard \Java class files.
If we save the above program in a file called
-\ident{HelloWorld.scala}, we can compile it by issuing the following
+\code{HelloWorld.scala}, we can compile it by issuing the following
command (the greater-than sign `\verb|>|' represents the shell prompt
and should not be typed):
\begin{verbatim}
> scalac HelloWorld.scala
\end{verbatim}
-This will generate a few class files in the current directory, one of
-which called \ident{HelloWorld.class}. This file contains a class
-which can be directly executed using the \java command, as will be
-seen in the following section.
+This will generate a few class files in the current directory. One of
+them will be called \code{HelloWorld.class}, and contains a class
+which can be directly executed using the \scala command, as the
+following section shows.
\subsection{Running the example}
\label{sec:running-example}
-Once compiled, a \Scala program can be run like a \Java program, using
-the \java command. However, a compiled \Scala program needs to access
-some support classes at run-time, which should be available through
-\Java's class path. These support classes are distributed in a JAR
-file called \path{scala.jar}, which lives in the directory
-\path{SCALA_HOME/lib}. Here \path{SCALA_HOME} is a place-holder for the
-name of the directory where the \Scala distribution was installed.
-
-The example above can therefore be executed using the command below,
-if we assume that the \Scala distribution was installed in
-\path{/usr/local}:
+Once compiled, a \Scala program can be run using the \scala command.
+Its usage is very similar to the \java command used to run \Java
+programs, and accepts the same options. The above example can be
+executed using the following command, which produces the expected
+output:
\begin{verbatim}
-> java -classpath /usr/local/lib/scala.jar:. HelloWorld
+> scala -classpath . HelloWorld
\end{verbatim}
\scalaprogramoutput{HelloWorld}
@@ -131,18 +123,19 @@ if we assume that the \Scala distribution was installed in
One of the strength of \Scala is that it makes it very easy to
interact with \Java code. Actually, the example of the previous
section showed this: to print the message on screen, we simply used a
-call to \Java's \ident{println} method on the (\Java) object
-\ident{System.out}.
+call to \Java's \code{println} method on the (\Java) object
+\code{System.out}.
All \Java code is accessible as easily from \Scala. Of course, it is
sometimes necessary to import classes, as one does in \Java, in order
-to be able to use them. All classes in the \ident{java.lang} packages
+to be able to use them. All classes in the \code{java.lang} packages
are imported by default, others need to be imported explicitly.
Let's look at another example to see this. The aim of this example is
to compute and print the factorial of 100 using \Java big integers
-(i.e. the class \ident{java.math.BigInteger}), since the result does
-not fit in a \Java integer. This program looks like this:
+(i.e. the class \code{BigInteger} in package \code{java.math}),
+since the result does not fit in a \Java integer. This program looks
+like this:
\begin{scalaprogram}{BigFactorial}
object BigFactorial {
import java.math.BigInteger, BigInteger._;
@@ -157,35 +150,35 @@ object BigFactorial {
}
\end{scalaprogram}
-\Scala's \ident{import} statement looks very similar to \Java's
+\Scala's \code{import} statement looks very similar to \Java's
equivalent, but an important difference appears here: to import all
the names of a package or class, one uses the underscore (\verb|_|)
character instead of the asterisk (\verb|*|). This is due to the fact
that, as we will see later, the asterisk is actually a valid \Scala
identifier.
-The \ident{import} statement above therefore starts by importing the
-class \ident{java.math.BigInteger}, and then all the names it
-contains. This makes the static fields \ident{ZERO} and \ident{ONE}
+The \code{import} statement above therefore starts by importing the
+class \code{BigInteger}, and then all the names it
+contains. This makes the static fields \code{ZERO} and \code{ONE}
directly visible.
-While we're talking about \ident{ZERO}, something must be said about
-the condition of the \ident{if} expression in method \ident{fact}. Is
-it really correct to check that \ident{x} is null by using the
-\ident{==} operator? A \Java programmer would say no, because in that
-language the \ident{==} operator compares objects by physical
+While we're talking about \code{ZERO}, something must be said about
+the condition of the \code{if} expression in method \code{fact}. Is
+it really correct to check that \code{x} is zero by using the
+\code{==} operator? A \Java programmer would say no, because in that
+language the \code{==} operator compares objects by physical
equality, and this is not what we want here. What we want to know is
-whether \ident{x} is \emph{some} big integer object representing zero,
+whether \code{x} is \emph{some} big integer object representing zero,
and there might be several of them. So a \Java programmer would use
-the \ident{equals} method to perform the comparison.
+the \code{equals} method to perform the comparison.
-The \Scala programmer, on the other hand, can use \ident{==} here
-because that operator compares objects according to the \ident{equals}
-method. Is \ident{==} just an alias for \ident{equals} then? Well,
-almost, but \ident{==} has one advantage over \ident{equals} in that
-it works also when the selector is the \ident{null} constant.
+The \Scala programmer, on the other hand, can use \code{==} here
+because that operator compares objects according to the \code{equals}
+method. Is \code{==} just an alias for \code{equals} then? Well,
+almost, but \code{==} has one advantage over \code{equals} in that
+it works also when the selector is the \code{null} constant.
-The \ident{fact} method also shows some characteristics of \Scala's
+The \code{fact} method also shows some characteristics of \Scala's
syntax. The first one is that the method body does not have to be
surrounded by curly braces if it consists of a single expression.
The second one is that methods taking one argument can be used with an
@@ -226,7 +219,7 @@ following expression, as we saw in the previous section:
\begin{lstlisting}
1.+(2.*(3./(x)))
\end{lstlisting}
-This also means that \ident{+}, \ident{*}, etc. are valid identifiers
+This also means that \code{+}, \code{*}, etc. are valid identifiers
in \Scala.
\subsection{Functions are objects}
@@ -248,39 +241,42 @@ user-interface code, to register call-back functions which get called
when some event occurs.
In the following program, the timer function is called
-\ident{oncePerSecond}, and it gets a call-back function as argument.
+\code{oncePerSecond}, and it gets a call-back function as argument.
The type of this function is written \verb|() => unit| and is the type
of all functions which have no arguments and return a value of type
-\ident{unit}. The main function of this program simply calls this
+\code{unit}. The main function of this program simply calls this
timer function with a call-back which prints a sentence on the
terminal. In other words, this program endlessly prints the sentence
\emph{time flies like an arrow} every second.
-
\begin{scalaprogram}{Timer}
object Timer {
def oncePerSecond(callback: () => unit): unit =
while (true) { callback(); Thread sleep 1000 };
def timeFlies(): unit =
- System.out.println("time flies like an arrow...");
+ Console.println("time flies like an arrow...");
def main(args: Array[String]): unit =
oncePerSecond(timeFlies);
}
\end{scalaprogram}
+We note that in order to print the string, we used method
+\code{println} of class \code{Console} instead of using the one from
+\code{System.out}. For now, \code{Console} can be seen as a \Scala
+equivalent of \Java's \code{System.out}.
\subsubsection{Anonymous functions}
\label{sec:anonymous-functions}
While this program is easy to understand, it can be refined a bit.
-First of all, notice that the function \ident{timeFlies} is only
-defined in order to be passed later to the \ident{oncePerSecond}
+First of all, notice that the function \code{timeFlies} is only
+defined in order to be passed later to the \code{oncePerSecond}
function. Having to name that function, which is only used once, might
seem unnecessary, and it would in fact be nice to be able to construct
-this function just as it is passed to \ident{oncePerSecond}. This is
+this function just as it is passed to \code{oncePerSecond}. This is
possible in \Scala using \emph{anonymous functions}, which are exactly
that: functions without a name. The revised version of our timer
-program using an anonymous function instead of \ident{timeFlies} looks
+program using an anonymous function instead of \code{timeFlies} looks
like that:
\begin{scalaprogram}{TimerAnonymous}
object TimerAnonymous {
@@ -289,14 +285,14 @@ object TimerAnonymous {
def main(args: Array[String]): unit =
oncePerSecond(() =>
- System.out.println("time flies like an arrow..."));
+ Console.println("time flies like an arrow..."));
}
\end{scalaprogram}
The presence of an anonymous function in this example is revealed by
the right arrow `\verb|=>|' which separates the function's argument
list from its body. In this example, the argument list is empty, as
witnessed by the empty pair of parenthesis on the left of the arrow.
-The body of the function is the same as the one of \ident{timeFlies}
+The body of the function is the same as the one of \code{timeFlies}
above.
% TODO fonctions avec environnement
@@ -319,13 +315,15 @@ class Complex(real: double, imaginary: double) {
}
\end{scalaprogram}
This complex class takes two arguments, which are the real and
-imaginary part of the complex. It then defines two methods, called
-\ident{re} and \ident{im} which give access to these two parts.
+imaginary part of the complex. These arguments must be passed when
+creating an instance of class \code{Complex}, as follows: \code{new
+ Complex(1.5, 2.3)}. The class contains two methods, called \code{re}
+and \code{im}, which give access to these two parts.
It should be noted that the return type of these two methods is not
given explicitly. It will be inferred automatically by the compiler,
which looks at the right-hand side of these methods and deduces that
-both return a value of type \ident{double}.
+both return a value of type \code{double}.
The compiler is not always able to infer types like it does here, and
there is unfortunately no simple rule to know exactly when it will be,
@@ -341,12 +339,12 @@ explicitly.
\subsection{Methods without arguments}
\label{sec:meth-wo-args}
-A small problem of the methods \ident{re} and \ident{im} is that, in
+A small problem of the methods \code{re} and \code{im} is that, in
order to call them, one has to put an empty pair of parenthesis after
their name, as the following example shows:
\begin{lstlisting}[escapechar=\#]
val c = new Complex(1.2, 3.4);
-System.out.println("imaginary part: " + c.im());
+Console.println("imaginary part: " + c.im());
\end{lstlisting}
It would be nicer to be able to access the real and imaginary parts
like if they were fields, without putting the empty pair of
@@ -354,7 +352,7 @@ parenthesis. This is perfectly doable in \Scala, simply by defining
the methods as methods \emph{without arguments}. These differ from
methods with zero arguments in that they don't have parenthesis after
their name, neither in their definition nor in their use. Our
-\ident{Complex} class can be rewritten as follows:
+\code{Complex} class can be rewritten as follows:
\begin{scalaprogram}{Complex2}
class Complex(real: double, imaginary: double) {
def re = real;
@@ -366,15 +364,15 @@ class Complex(real: double, imaginary: double) {
\label{sec:inheritance}
All classes in \Scala inherit from a super-class. When no super-class
-is specified, as in the \ident{Complex} example of previous section,
-\ident{scala.Object} is implicitly used.
+is specified, as in the \code{Complex} example of previous section,
+\code{scala.Object} is implicitly used.
It is possible to override methods inherited from a super-class in
\Scala. It is however mandatory to explicitly specify that a method
-overrides another one using the \ident{override} modifier, in order to
-avoid accidental overriding. As an example, our \ident{Complex} class
-can be augmented with a redefinition of the \ident{toString} method
-inherited from \ident{Object}.
+overrides another one using the \code{override} modifier, in order to
+avoid accidental overriding. As an example, our \code{Complex} class
+can be augmented with a redefinition of the \code{toString} method
+inherited from \code{Object}.
\begin{scalaprogram}{Complex3}
class Complex(real: double, imaginary: double) {
def re = real;
@@ -387,6 +385,207 @@ class Complex(real: double, imaginary: double) {
\section{Case classes and pattern matching}
\label{sec:case-classes-pattern}
+A kind of data structure that often appears in programs is the tree.
+For example, interpreters and compilers usually represent programs
+internally as trees; XML documents are trees; and several kinds of
+containers are based on trees, like red-black trees.
+
+We will now examine how such trees are represented and manipulated in
+\Scala through a small calculator program. The aim of this program is
+to manipulate very simple arithmetic expressions composed of sums,
+integer constants and variables. Examples of such expressions include
+$1+2$ or $(x+x)+(7+y)$.
+
+We first have to decide on a representation for such expressions. The
+most natural one to use is the tree, where nodes are operations (here,
+the addition) and leaves are values (here constants or variables).
+
+In \Java, such a tree would be represented using an abstract
+super-class for the trees, and one concrete sub-class per node or
+leaf. In a functional programming language, one would use an algebraic
+data-type for the same purpose. \Scala provides the concept of
+\emph{case classes} which is somewhat in between the two. Here is how
+they can be used to define the type of the trees for our example:
+\beginscalaprogram{Calculator}
+\begin{scalacode}
+abstract class Tree;
+case class Sum(l: Tree, r: Tree) extends Tree;
+case class Var(n: String) extends Tree;
+case class Const(v: int) extends Tree;
+\end{scalacode}
+The fact that classes \code{Sum}, \code{Var} and \code{Const} are
+declared as case classes means that they differ from standard classes
+in several respects:
+\begin{itemize}
+\item the \code{new} keyword is not mandatory to create instances of
+ these classes (i.e. one can write \code{Const(5)} instead of
+ \code{new Const(5)}),
+\item getter functions are automatically defined for the constructor
+ parameters (i.e. it is possible to get the value of the \code{v}
+ constructor parameter of some instance \code{c} of class
+ \code{Const} just by writing \code{c.v}),
+\item default definitions for methods \code{equals} and
+ \code{hashCode} are provided, which work on the \emph{structure} of
+ the instances and not on their identity,
+\item a default definition for method \code{toString} is provided, and
+ prints the value in a ``source form'' (e.g. the tree for expression
+ $x+1$ prints as \code{Sum(Var(x),Const(1))}),
+\item instances of these classes \code{Tree} can be decomposed through
+ \emph{pattern matching} as we will see below.
+\end{itemize}
+
+Now that we have defined the data-type to represent our arithmetic
+expressions, we can start defining operations to manipulate them. We
+will start with a function to evaluate an expression in some
+\emph{environment}. The aim of the environment is to give values to
+variables. For example, the expression $x+1$ evaluated in an
+environment which associates the value $5$ to variable $x$, written
+\{$x\rightarrow 5$\}, gives $6$ as result.
+
+We therefore have to find a way to represent environments. We could of
+course use some associative data-structure like a hash table, but we
+can also directly use functions! An environment is really nothing more
+than a function which associates a value to a (variable) name. The
+environment \{$x\rightarrow 5$\} given above can simply be written as
+follows in \Scala:
+\begin{lstlisting}
+ { case "x" => 5 }
+\end{lstlisting}
+This notation defines a function which, when given the string
+\code{"x"} as argument, returns the integer 5, and fails with an
+exception otherwise.
+
+Before writing the evaluation function, let us give a name to the type
+of the environments. We could of course always use the type
+\code{String => int} for environments, but it simplifies the program
+if we introduce a name for this type, and makes future changes easier.
+This is accomplished in \Scala with the following notation:
+\begin{scalainvisiblecode}
+object Calculator {
+\end{scalainvisiblecode}
+\begin{scalacode}
+ type Environment = (String => int);
+\end{scalacode}
+From then on, the type \code{Environment} can be used as an alias of
+the type of functions from \code{String} to \code{int}.
+
+We can now give the definition of the evaluation function.
+Conceptually, it is very simple: the value of a sum of two expressions
+is simply the sum of the value of these expressions; the value of a
+variable is obtained directly from the environment; and the value of a
+constant is the constant itself. Expressing this in \Scala is not more
+difficult:
+\begin{scalacode}
+ def eval(t: Tree, env: Environment): int = t match {
+ case Sum(l, r) => eval(l, env) + eval(r, env)
+ case Var(n) => env(n)
+ case Const(v) => v
+ }
+\end{scalacode}
+This evaluation function works by performing \emph{pattern matching}
+on the tree \code{t}. Intuitively, the meaning of the above definition
+should be clear:
+\begin{enumerate}
+\item it first checks if the tree \code{t} is a \code{Sum}, and if it
+ is, it binds the left sub-tree to a new variable called \code{l} and
+ the right sub-tree to a variable called \code{r}, and then proceeds
+ with the evaluation of the expression following the arrow; this
+ expression can (and does) make use of the variables bound by the
+ pattern appearing on the left of the arrow, i.e. \code{l} and
+ \code{r},
+\item if the first check does not succeed, that is if the tree is not
+ a \code{Sum}, it goes on and checks if \code{t} is a \code{Var}; if
+ it is, it binds the name contained in the \code{Var} node to a
+ variable \code{n} and proceeds with the right-hand expression,
+\item if the second check also fails, that is if \code{t} is neither a
+ \code{Sum} nor a \code{Var}, it checks if it is a \code{Const}, and
+ if it is, it binds the value contained in the \code{Const} node to a
+ variable \code{v} and proceeds with the right-hand side,
+\item finally, if all checks fail, an exception is raised to signal
+ the failure of the pattern matching expression; this could happen
+ here only if more sub-classes of \code{Tree} were declared.
+\end{enumerate}
+We see that the basic idea of pattern matching is to attempt to match
+a value to a series of patterns, and as soon as a pattern matches,
+extract and name various parts of the value, to finally evaluate some
+code which typically makes use of these named parts.
+
+A seasoned object-oriented programmer might wonder why we did not
+define \code{eval} as a \emph{method} of class \code{Tree} and its
+subclasses. We could have done it actually, since \Scala allows method
+definitions in case classes just like in normal classes. Deciding
+whether to use pattern matching or methods is therefore a matter of
+taste, but it also has important implications on extensibility:
+\begin{itemize}
+\item when using methods, it is easy to add a new kind of node as this
+ can be done just by defining the sub-class of \code{Tree} for it; on
+ the other hand, adding a new operation to manipulate the tree is
+ tedious, as it requires modifications to all sub-classes of
+ \code{Tree},
+\item when using pattern matching, the situation is reversed: adding a
+ new kind of node requires the modification of all functions which do
+ pattern matching on the tree, to take the new node into account; on
+ the other hand, adding a new operation is easy, by just defining it
+ as an independent function.
+\end{itemize}
+
+To explore pattern matching further, let us define another operation
+on arithmetic expressions: symbolic derivation. The reader might
+remember the following rules regarding this operation:
+\begin{enumerate}
+\item the derivative of a sum is the sum of the derivatives,
+\item the derivative of some variable $v$ is one if $v$ is the
+ variable relative to which the derivation takes place, and zero
+ otherwise,
+\item the derivative of a constant is zero.
+\end{enumerate}
+These rules can be translated almost literally into \Scala code, to
+obtain the following definition:
+\begin{scalacode}
+ def derive(t: Tree, v: String): Tree = t match {
+ case Sum(l, r) => Sum(derive(l, v), derive(r, v))
+ case Var(n) if (v == n) => Const(1)
+ case _ => Const(0)
+ }
+\end{scalacode}
+This function introduces two new concepts related to pattern matching.
+First of all, the \code{case} expression for variables has a
+\emph{guard}, an expression following the \code{if} keyword. This
+guard prevents pattern matching from succeeding unless its expression
+is true. Here it is used to make sure that we return the constant 1
+only if the name of the variable being derived is the same as the
+derivation variable \code{v}. The second new feature of pattern
+matching used here is the \emph{wild-card}, written \code{_}, which is
+a pattern matching any value, without giving it a name.
+
+We did not explore the whole power of pattern matching yet, but we
+will stop here in order to keep this document short. We still want to
+see how the two functions above perform on a real example. For that
+purpose, let's write a simple \code{main} function which performs
+several operations on the expression $(x+x)+(7+y)$: it first computes
+its value in the environment $\{x\rightarrow 5, y\rightarrow 7\}$, then
+computes its derivative relative to $x$ and then $y$.
+\begin{scalacode}
+ def main(args: Array[String]): Unit = {
+ val exp: Tree = Sum(Sum(Var("x"),Var("x")),Sum(Const(7),Var("y")));
+ val env: Environment = { case "x" => 5 case "y" => 7 };
+ Console.println("Expression: " + exp);
+ Console.println("Evaluation with x=5, y=7: " + eval(exp, env));
+ Console.println("Derivative relative to x:\n " + derive(exp, "x"));
+ Console.println("Derivative relative to y:\n " + derive(exp, "y"));
+ }
+\end{scalacode}
+\begin{scalainvisiblecode}
+} // object Calculator
+\end{scalainvisiblecode}
+\endscalaprogram{Calculator}
+Executing this program, we get the expected output:
+\scalaprogramoutput{Calculator}
+By examining the output, we see that the result of the derivative
+should be simplified before being presented to the user. Defining a
+basic simplification function using pattern matching is an interesting
+(but surprisingly tricky) problem, left as an exercise for the reader.
+
\section{Mixins}
\label{sec:mixins}
@@ -401,10 +600,10 @@ interface, and inherits all the code contained in the mixin.
To see the usefulness of mixins, let's look at a classical example:
ordered objects. It is often useful to be able to compare objects of a
given class among themselves, for example to sort them. In \Java,
-objects which are comparable implement the \ident{Comparable}
+objects which are comparable implement the \code{Comparable}
interface. In \Scala, we can do a bit better than in \Java by defining
-our equivalent of \ident{Comparable} as a mixin, which we will call
-\ident{Ord}.
+our equivalent of \code{Comparable} as a mixin, which we will call
+\code{Ord}.
When comparing objects, six different predicates can be useful:
smaller, smaller or equal, equal, not equal, greater or equal, and
@@ -415,26 +614,31 @@ express the other ones. In \Scala, all these observations can be
nicely captured by the following mixin declaration:
\beginscalaprogram{Ord}
\begin{scalacode}
- abstract class Ord {
+abstract class Ord {
def < (that: Any): boolean;
def <=(that: Any): boolean = (this < that) || (this == that);
def > (that: Any): boolean = !(this <= that);
def >=(that: Any): boolean = !(this < that);
}
\end{scalacode}
-This definition both creates a new type called \ident{Ord}, which
-plays the same role as \Java's \ident{Comparable} interface, and
+This definition both creates a new type called \code{Ord}, which
+plays the same role as \Java's \code{Comparable} interface, and
default implementations of three predicates in terms of a fourth,
abstract one. The predicates for equality and inequality do not appear
here since they are by default present in all objects.
+The type \code{Any} which is used above is the type which is a
+super-type of all other types in \Scala. It can be seen as a more
+general version of \Java's \code{Object} type, since it is also a
+super-type of basic types like \code{int}, \code{float}, etc.
+
To make objects of a class comparable, it is therefore sufficient to
define the predicates which test equality and inferiority, and mix in
-the \ident{Ord} class above. As an example, let's define a
-\ident{Date} class representing dates in the Gregorian calendar. Such
+the \code{Ord} class above. As an example, let's define a
+\code{Date} class representing dates in the Gregorian calendar. Such
dates are composed of a day, a month and a year, which we will all
represent as integers. We therefore start the definition of the
-\ident{Date} class as follows:
+\code{Date} class as follows:
\begin{scalacode}
class Date(y: int, m: int, d: int) with Ord {
def year = y;
@@ -445,11 +649,11 @@ class Date(y: int, m: int, d: int) with Ord {
\end{scalacode}
The important part here is the \code{with Ord} declaration which
follows the class name and parameters. It declares that the
-\ident{Date} class inherits from the \ident{Ord} class as a mixin.
+\code{Date} class inherits from the \code{Ord} class as a mixin.
-Then, we redefine the \ident{equals} method, inherited from
-\ident{Object}, so that it correctly compares dates by comparing their
-individual fields. The default implementation of \ident{equals} is not
+Then, we redefine the \code{equals} method, inherited from
+\code{Object}, so that it correctly compares dates by comparing their
+individual fields. The default implementation of \code{equals} is not
usable, because as in \Java it compares object physically. We arrive
at the following definition:
\begin{scalacode}
@@ -460,22 +664,22 @@ at the following definition:
}
}
\end{scalacode}
-This method makes use of the predefined methods \ident{isInstanceOf}
-and \ident{asInstanceOf}. The first one, \ident{isInstanceOf},
-corresponds to \Java's \ident{instanceof} operator, and returns true
+This method makes use of the predefined methods \code{isInstanceOf}
+and \code{asInstanceOf}. The first one, \code{isInstanceOf},
+corresponds to \Java's \code{instanceof} operator, and returns true
if and only if the object on which it is applied is an instance of the
-given type. The second one, \ident{AsInstanceOf}, corresponds to
+given type. The second one, \code{asInstanceOf}, corresponds to
\Java's cast operator: If the object is an instance of the given type,
-it is viewed as such, and otherwise a \ident{ClassCastException} is
+it is viewed as such, otherwise a \code{ClassCastException} is
thrown.
Finally, the last method to define is the predicate which tests for
inferiority, as follows. It makes use of another predefined method,
-\ident{error}, which throws an exception with the given error message.
+\code{error}, which throws an exception with the given error message.
\begin{scalacode}
def <(that: Any): boolean = {
if (!that.isInstanceOf[Date])
- error("cannot compare " + that + " with a Date");
+ error("cannot compare " + that + " and a Date");
val o = that.asInstanceOf[Date];
(year < o.year)
@@ -484,31 +688,93 @@ inferiority, as follows. It makes use of another predefined method,
}
}
\end{scalacode}
-This completes the definition of the \ident{Date} class. Instances of
+\endscalaprogram{Ord}
+This completes the definition of the \code{Date} class. Instances of
this class can be seen either as dates or as comparable objects.
Moreover, they all define the six comparison predicates mentioned
-above: \ident{equals} and \ident{<} because they appear directly in
-the definition of the \ident{Date} class, and the others because they
-are inherited from the \ident{Ord} mixin.
+above: \code{equals} and \code{<} because they appear directly in
+the definition of the \code{Date} class, and the others because they
+are inherited from the \code{Ord} mixin.
Mixins are useful in other situations than the one shown here, of
course, but discussing their applications in length is outside the
scope of this document.
-
\section{Genericity}
\label{sec:genericity}
+The last characteristic of \Scala we will explore in this tutorial is
+genericity. \Java programmers should be well aware of the problems
+posed by the lack of genericity in their language, a shortcoming which
+is addressed in \Java 1.5.
+
+Genericity is the ability to write code parametrised by types. For
+example, a programmer writing a library for linked lists faces the
+problem of deciding which type to give to the elements of the list.
+Since this list is meant to be used in many different contexts, it is
+not possible to decide that the type of the elements has to be, say,
+\code{int}. This would be completely arbitrary and overly
+restrictive.
+
+\Java programmers resort to using \code{Object}, which is the
+super-type of all objects. This solution is however far from being
+ideal, since it doesn't work for basic types (\code{int},
+\code{long}, \code{float}, etc.) and it implies that a lot of
+dynamic type casts have to be inserted by the programmer.
+
+\Scala makes it possible to define generic classes (and methods) to
+solve this problem. Let us examine this with an example of the
+simplest container class possible: a reference, which can either be
+empty or point to an object of some type.
+\beginscalaprogram{Reference}
+\begin{scalacode}
+class Reference[a] {
+ private var contents: a = _;
+ def set(value: a): Unit = { contents = value; }
+ def get: a = contents;
+}
+\end{scalacode}
+The class \code{Reference} is parametrised by a type, called \code{a},
+which is the type of its element. This type is used in the body of the
+class as the type of the \code{contents} variable, the argument of
+the \code{set} method, and the return type of the \code{get} method.
+
+The above code sample introduces variables in \Scala, which should not
+require further explanations. It is however interesting to see that
+the initial value given to that variable is \code{_}, which represents
+a default value. This default value is 0 for numeric types,
+\code{false} for the boolean type, \code{()} for the unit type and
+\code{null} for all object types.
+
+To use this \code{Reference} class, one needs to specify which type to use
+for the type parameter \code{a}, that is the type of the element
+contained by the cell. For example, to create and use a cell holding
+an integer, one could write the following:
+\begin{scalacode}
+object IntegerReference {
+ def main(args: Array[String]): Unit = {
+ val cell = new Reference[Int];
+ cell.set(13);
+ Console.print("Reference contains the half of " + (cell.get * 2));
+ }
+}
+\end{scalacode}
+\endscalaprogram{Reference}
+As can be seen in that example, it is not necessary to cast the value
+returned by the \code{get} method before using it as an integer. It
+is also not possible to store anything but an integer in that
+particular cell, since it was declared as holding an integer.
\section{Conclusion}
\label{sec:conclusion}
This document gave a quick overview of the \Scala language and
presented some basic examples. The interested reader can go on by
-reading the companion document \textit{Scala By Example\/} and consult
-the \textit{Scala Language Specification\/} when needed.
+reading the companion document \textit{Scala By Example\/}, which
+contains much more advanced examples, and consult the \textit{Scala
+ Language Specification\/} when needed.
\end{document}
-% LocalWords: mixins mixin mixin's
+% LocalWords: mixins mixin mixin's genericity