*** empty log message ***
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@2418 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
cf69c6449c
commit
bcfd151a69
|
@ -23,8 +23,8 @@ interesting programming techniques. The present informal exposition is
|
||||||
meant to be complemented by the Java Language Reference Manual which
|
meant to be complemented by the Java Language Reference Manual which
|
||||||
specifies Scala in a more detailed and precise way.
|
specifies Scala in a more detailed and precise way.
|
||||||
|
|
||||||
\paragraph{Acknowledgement}
|
\paragraph{Acknowledgment}
|
||||||
We owe a great dept to Sussman and Abelson's wonderful book
|
We owe a great debt to Abelson's and Sussman's wonderful book
|
||||||
``Structure and Interpretation of Computer
|
``Structure and Interpretation of Computer
|
||||||
Programs''\cite{abelson-sussman:structure}. Many of their examples and
|
Programs''\cite{abelson-sussman:structure}. Many of their examples and
|
||||||
exercises are also present here. Of course, the working language has
|
exercises are also present here. Of course, the working language has
|
||||||
|
@ -86,7 +86,7 @@ instance, the name of the array \code{a} is visible in functions
|
||||||
parameter to them.
|
parameter to them.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
So far, Scala looks like a fairly conventional language with some
|
So far, Scala looks like a fairly conventional language with some
|
||||||
syntactic pecularities. In fact it is possible to write programs in a
|
syntactic peculiarities. In fact it is possible to write programs in a
|
||||||
conventional imperative or object-oriented style. This is important
|
conventional imperative or object-oriented style. This is important
|
||||||
because it is one of the things that makes it easy to combine Scala
|
because it is one of the things that makes it easy to combine Scala
|
||||||
components with components written in mainstream languages such as
|
components with components written in mainstream languages such as
|
||||||
|
@ -106,7 +106,7 @@ def sort(xs: List[int]): List[int] = {
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
The functional program works with lists instead of arrays.\footnote{In
|
The functional program works with lists instead of arrays.\footnote{In
|
||||||
a future complete implemenetation of Scala, we could also have used arrays
|
a future complete implementation of Scala, we could also have used arrays
|
||||||
instead of lists, but at the moment arrays do not yet support
|
instead of lists, but at the moment arrays do not yet support
|
||||||
\code{filter} and \code{:::}.}
|
\code{filter} and \code{:::}.}
|
||||||
It captures the essence of the quicksort algorithm in a concise way:
|
It captures the essence of the quicksort algorithm in a concise way:
|
||||||
|
@ -114,7 +114,7 @@ It captures the essence of the quicksort algorithm in a concise way:
|
||||||
\item Pick an element in the middle of the list as a pivot.
|
\item Pick an element in the middle of the list as a pivot.
|
||||||
\item Partition the lists into two sub-lists containing elements that
|
\item Partition the lists into two sub-lists containing elements that
|
||||||
are less than, respectively greater than the pivot element, and a
|
are less than, respectively greater than the pivot element, and a
|
||||||
third list which contains elements equal to privot.
|
third list which contains elements equal to pivot.
|
||||||
\item Sort the first two sub-lists by a recursive invocation of
|
\item Sort the first two sub-lists by a recursive invocation of
|
||||||
the sort function.\footnote{This is not quite what the imperative algorithm does;
|
the sort function.\footnote{This is not quite what the imperative algorithm does;
|
||||||
the latter partitions the array into two sub-arrays containing elements
|
the latter partitions the array into two sub-arrays containing elements
|
||||||
|
@ -328,7 +328,7 @@ on one item. Objects of this class are created by indicating
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
The process behavior is defined by its \code{run} method. That method
|
The process behavior is defined by its \code{run} method. That method
|
||||||
repeatedly selects (using \code{receiveWithin}) a message and reacts to it,
|
repeatedly selects (using \code{receiveWithin}) a message and reacts to it,
|
||||||
until the auction is closed, which is signalled by a \code{TIMEOUT}
|
until the auction is closed, which is signaled by a \code{TIMEOUT}
|
||||||
message. Before finally stopping, it stays active for another period
|
message. Before finally stopping, it stays active for another period
|
||||||
determined by the \code{timeToShutdown} constant and replies to
|
determined by the \code{timeToShutdown} constant and replies to
|
||||||
further offers that the auction is closed.
|
further offers that the auction is closed.
|
||||||
|
@ -632,7 +632,7 @@ def sqrtIter(guess: double, x: double): double =
|
||||||
else sqrtIter(improve(guess, x), x);
|
else sqrtIter(improve(guess, x), x);
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Note that \code{sqrtIter} calls itself recursively. Loops in
|
Note that \code{sqrtIter} calls itself recursively. Loops in
|
||||||
imperative programs can always be modelled by recursion in functional
|
imperative programs can always be modeled by recursion in functional
|
||||||
programs.
|
programs.
|
||||||
|
|
||||||
Note also that the definition of \code{sqrtIter} contains a return
|
Note also that the definition of \code{sqrtIter} contains a return
|
||||||
|
@ -654,7 +654,7 @@ def isGoodEnough(guess: double, x: double) =
|
||||||
abs(square(guess) - x) < 0.001;
|
abs(square(guess) - x) < 0.001;
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
Finally, the \code{sqrt} function itself is defined by an aplication
|
Finally, the \code{sqrt} function itself is defined by an application
|
||||||
of \code{sqrtIter}.
|
of \code{sqrtIter}.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def sqrt(x: double) = sqrtIter(1.0, x);
|
def sqrt(x: double) = sqrtIter(1.0, x);
|
||||||
|
@ -800,7 +800,7 @@ executed in constant space.
|
||||||
|
|
||||||
By contrast, the recursive call in \code{factorial} is followed by a
|
By contrast, the recursive call in \code{factorial} is followed by a
|
||||||
multiplication. Hence, a new stack frame is allocated for the
|
multiplication. Hence, a new stack frame is allocated for the
|
||||||
recursive instance of factorial, and is decallocated after that
|
recursive instance of factorial, and is deallocated after that
|
||||||
instance has finished. The given formulation of the factorial function
|
instance has finished. The given formulation of the factorial function
|
||||||
is not tail-recursive; it needs space proportional to its input
|
is not tail-recursive; it needs space proportional to its input
|
||||||
parameter for its execution.
|
parameter for its execution.
|
||||||
|
@ -810,7 +810,7 @@ More generally, if the last action of a function is a call to another
|
||||||
both functions. Such calls are called ``tail calls''. In principle,
|
both functions. Such calls are called ``tail calls''. In principle,
|
||||||
tail calls can always re-use the stack frame of the calling function.
|
tail calls can always re-use the stack frame of the calling function.
|
||||||
However, some run-time environments (such as the Java VM) lack the
|
However, some run-time environments (such as the Java VM) lack the
|
||||||
primititives to make stack frame re-use for tail calls efficient. A
|
primitives to make stack frame re-use for tail calls efficient. A
|
||||||
production quality Scala implementation is therefore only required to
|
production quality Scala implementation is therefore only required to
|
||||||
re-use the stack frame of a directly tail-recursive function whose
|
re-use the stack frame of a directly tail-recursive function whose
|
||||||
last action is a call to itself. Other tail calls might be optimized
|
last action is a call to itself. Other tail calls might be optimized
|
||||||
|
@ -1377,7 +1377,7 @@ integers, as well as a private field \code{g} which contains the
|
||||||
\code{gcd} of the constructor arguments. These members are inaccessible
|
\code{gcd} of the constructor arguments. These members are inaccessible
|
||||||
outside class \code{Rational}. They are used in the implementation of
|
outside class \code{Rational}. They are used in the implementation of
|
||||||
the class to eliminate common factors in the constructor arguments in
|
the class to eliminate common factors in the constructor arguments in
|
||||||
order to ensure that nominator and denominator are always in
|
order to ensure that numerator and denominator are always in
|
||||||
normalized form.
|
normalized form.
|
||||||
|
|
||||||
\paragraph{Creating and Accessing Objects}
|
\paragraph{Creating and Accessing Objects}
|
||||||
|
@ -1478,7 +1478,7 @@ that clients do not have to be rewritten because of that change.
|
||||||
|
|
||||||
Consider the task of writing a class for sets of integer numbers with
|
Consider the task of writing a class for sets of integer numbers with
|
||||||
two operations, \code{incl} and \code{contains}. \code{(s incl x)}
|
two operations, \code{incl} and \code{contains}. \code{(s incl x)}
|
||||||
should return a new set which contains the element \code{x} togther
|
should return a new set which contains the element \code{x} together
|
||||||
with all the elements of set \code{s}. \code{(s contains x)} should
|
with all the elements of set \code{s}. \code{(s contains x)} should
|
||||||
return true if the set \code{s} contains the element \code{x}, and
|
return true if the set \code{s} contains the element \code{x}, and
|
||||||
should return \code{false} otherwise. The interface of such sets is
|
should return \code{false} otherwise. The interface of such sets is
|
||||||
|
@ -1750,7 +1750,7 @@ trait Nat {
|
||||||
def - (that: Nat): Nat;
|
def - (that: Nat): Nat;
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
To implement the operations of class \code{Nat}, we define a subobject
|
To implement the operations of class \code{Nat}, we define a sub-object
|
||||||
\code{Zero} and a subclass \code{Succ} (for successor). Each number
|
\code{Zero} and a subclass \code{Succ} (for successor). Each number
|
||||||
\code{N} is represented as \code{N} applications of the \code{Succ}
|
\code{N} is represented as \code{N} applications of the \code{Succ}
|
||||||
constructor to \code{Zero}:
|
constructor to \code{Zero}:
|
||||||
|
@ -2027,7 +2027,7 @@ would be added. Hence, one can now construct expression trees a bit more concise
|
||||||
Sum(Sum(Number(1), Number(2)), Number(3))
|
Sum(Sum(Number(1), Number(2)), Number(3))
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\item Case classes and case objects
|
\item Case classes and case objects
|
||||||
implicity come with implementations of methods
|
implicitly come with implementations of methods
|
||||||
\code{toString}, \code{equals} and \code{hashCode}, which override the
|
\code{toString}, \code{equals} and \code{hashCode}, which override the
|
||||||
methods with the same name in class \code{AnyRef}. The implementation
|
methods with the same name in class \code{AnyRef}. The implementation
|
||||||
of these methods takes in each case the structure of a member of a
|
of these methods takes in each case the structure of a member of a
|
||||||
|
@ -2056,7 +2056,7 @@ methods. It computes a hash code from the case class constructor name
|
||||||
and the hash codes of the constructor arguments, instead of from the object's
|
and the hash codes of the constructor arguments, instead of from the object's
|
||||||
address, which is what the as the default implementation of \code{hashCode} does.
|
address, which is what the as the default implementation of \code{hashCode} does.
|
||||||
\item
|
\item
|
||||||
Case classes implicity come with nullary accessor methods which
|
Case classes implicitly come with nullary accessor methods which
|
||||||
retrieve the constructor arguments.
|
retrieve the constructor arguments.
|
||||||
In our example, \code{Number} would obtain an accessor method
|
In our example, \code{Number} would obtain an accessor method
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
|
@ -2418,7 +2418,7 @@ val s = new EmptySet[java.io.File]
|
||||||
$\mbox{\sl parameter bound}$ Ord[java.io.File].
|
$\mbox{\sl parameter bound}$ Ord[java.io.File].
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
To conclude the discussion of type parameter
|
To conclude the discussion of type parameter
|
||||||
bounds, here is the defintion of trait \code{Ord} in scala.
|
bounds, here is the definition of trait \code{Ord} in scala.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
package scala;
|
package scala;
|
||||||
trait Ord[t <: Ord[t]]: t {
|
trait Ord[t <: Ord[t]]: t {
|
||||||
|
@ -2519,7 +2519,7 @@ class Array[+a] {
|
||||||
$\mbox{\sl appears in contravariant position.}$
|
$\mbox{\sl appears in contravariant position.}$
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
So far, so good. Intuitively, the compiler was correect in rejecting
|
So far, so good. Intuitively, the compiler was correct in rejecting
|
||||||
the \code{update} method in a co-variant class because \code{update}
|
the \code{update} method in a co-variant class because \code{update}
|
||||||
potentially changes state, and therefore undermines the soundness of
|
potentially changes state, and therefore undermines the soundness of
|
||||||
co-variant subtyping.
|
co-variant subtyping.
|
||||||
|
@ -2580,7 +2580,7 @@ often suggest a useful generalization of the contested method.
|
||||||
\section{Least Types}
|
\section{Least Types}
|
||||||
|
|
||||||
Scala does not allow one to parameterize objects with types. That's
|
Scala does not allow one to parameterize objects with types. That's
|
||||||
why we orginally defined a generic class \code{EmptyStack[a]}, even
|
why we originally defined a generic class \code{EmptyStack[a]}, even
|
||||||
though a single value denoting empty stacks of arbitrary type would
|
though a single value denoting empty stacks of arbitrary type would
|
||||||
do. For co-variant stacks, however, one can use the following idiom:
|
do. For co-variant stacks, however, one can use the following idiom:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
|
@ -2677,14 +2677,14 @@ follows.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def divmod(x: int, y: int) = Pair(x / y, x % y)
|
def divmod(x: int, y: int) = Pair(x / y, x % y)
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
How are elements of tuples acessed? Since tuples are case classes,
|
How are elements of tuples accessed? Since tuples are case classes,
|
||||||
there are two possibilities. One can either access a tuple's fields
|
there are two possibilities. One can either access a tuple's fields
|
||||||
using the names of the constructor parameters \lstinline@_$i$@, as in the following example:
|
using the names of the constructor parameters \lstinline@_$i$@, as in the following example:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
val xy = divmod(x, y);
|
val xy = divmod(x, y);
|
||||||
System.out.println("quotient: " + x._1 + ", rest: " + x._2);
|
System.out.println("quotient: " + x._1 + ", rest: " + x._2);
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Or one uses pattern matching on tuples, as in the following erample:
|
Or one uses pattern matching on tuples, as in the following example:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
divmod(x, y) match {
|
divmod(x, y) match {
|
||||||
case Pair(n, d) =>
|
case Pair(n, d) =>
|
||||||
|
@ -3153,7 +3153,7 @@ computation over lists, like:
|
||||||
\item extracting from a list all elements satisfying a criterion.
|
\item extracting from a list all elements satisfying a criterion.
|
||||||
\item combine the elements of a list using some operator.
|
\item combine the elements of a list using some operator.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
Functional programming languages enable programmers to write eneral
|
Functional programming languages enable programmers to write general
|
||||||
functions which implement patterns like this by means of higher order
|
functions which implement patterns like this by means of higher order
|
||||||
functions. We now discuss a set of commonly used higher-order
|
functions. We now discuss a set of commonly used higher-order
|
||||||
functions, which are implemented as methods in class \code{List}.
|
functions, which are implemented as methods in class \code{List}.
|
||||||
|
@ -3176,7 +3176,7 @@ abstract class List[a] { ...
|
||||||
case x :: xs => f(x) :: xs.map(f)
|
case x :: xs => f(x) :: xs.map(f)
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Using \code{map}, \code{scaleList} can be more consisely written as follows.
|
Using \code{map}, \code{scaleList} can be more concisely written as follows.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def scaleList(xs: List[double], factor: double) =
|
def scaleList(xs: List[double], factor: double) =
|
||||||
xs map (x => x * factor)
|
xs map (x => x * factor)
|
||||||
|
@ -3237,7 +3237,7 @@ This pattern is generalized to the \code{filter} method of class \code{List}:
|
||||||
case x :: xs => if (p(x)) x :: xs.filter(p) else xs.filter(p)
|
case x :: xs => if (p(x)) x :: xs.filter(p) else xs.filter(p)
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Using \code{filter}, \code{posElems} can be more consisely written as
|
Using \code{filter}, \code{posElems} can be more concisely written as
|
||||||
follows.
|
follows.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def posElems(xs: List[int]): List[int] =
|
def posElems(xs: List[int]): List[int] =
|
||||||
|
@ -3260,7 +3260,7 @@ To illustrate the use of \code{forall}, consider the question whether
|
||||||
a number if prime. Remember that a number $n$ is prime of it can be
|
a number if prime. Remember that a number $n$ is prime of it can be
|
||||||
divided without remainder only by one and itself. The most direct
|
divided without remainder only by one and itself. The most direct
|
||||||
translation of this definition would test that $n$ divided by all
|
translation of this definition would test that $n$ divided by all
|
||||||
numbers from 2 upto and excluding itself gives a non-zero
|
numbers from 2 up to and excluding itself gives a non-zero
|
||||||
remainder. This list of numbers can be generated using a function
|
remainder. This list of numbers can be generated using a function
|
||||||
\code{List.range} which is defined in object \code{List} as follows.
|
\code{List.range} which is defined in object \code{List} as follows.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
|
@ -3270,7 +3270,7 @@ object List { ...
|
||||||
if (from >= end) Nil else from :: range(from + 1, end);
|
if (from >= end) Nil else from :: range(from + 1, end);
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
For example, \code{List.range(2, n)}
|
For example, \code{List.range(2, n)}
|
||||||
generates the list of all integers from 2 upto and excluding $n$.
|
generates the list of all integers from 2 up to and excluding $n$.
|
||||||
The function \code{isPrime} can now simply be defined as follows.
|
The function \code{isPrime} can now simply be defined as follows.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def isPrime(n: int) =
|
def isPrime(n: int) =
|
||||||
|
@ -3301,7 +3301,7 @@ def product(xs: List[int]): int = xs match {
|
||||||
case y :: ys => y * product(ys)
|
case y :: ys => y * product(ys)
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
But we can also use the generaliztion of this program scheme embodied
|
But we can also use the generalization of this program scheme embodied
|
||||||
in the \code{reduceLeft} method of class \code{List}. This method
|
in the \code{reduceLeft} method of class \code{List}. This method
|
||||||
inserts a given binary operator between adjacent elements of a given list.
|
inserts a given binary operator between adjacent elements of a given list.
|
||||||
E.g.\
|
E.g.\
|
||||||
|
@ -3919,7 +3919,7 @@ constructions for dealing with lists. But sometimes the level of
|
||||||
abstraction required by these functions makes a program hard to
|
abstraction required by these functions makes a program hard to
|
||||||
understand.
|
understand.
|
||||||
|
|
||||||
To help understandbility, Scala has a special notation which
|
To help understandability, Scala has a special notation which
|
||||||
simplifies common patterns of applications of higher-order functions.
|
simplifies common patterns of applications of higher-order functions.
|
||||||
This notation builds a bridge between set-comprehensions in
|
This notation builds a bridge between set-comprehensions in
|
||||||
mathematics and for-loops in imperative languages such as C or
|
mathematics and for-loops in imperative languages such as C or
|
||||||
|
@ -3977,15 +3977,15 @@ be written as follows.
|
||||||
|
|
||||||
For-comprehensions are especially useful for solving combinatorial
|
For-comprehensions are especially useful for solving combinatorial
|
||||||
puzzles. An example of such a puzzle is the 8-queens problem: Given a
|
puzzles. An example of such a puzzle is the 8-queens problem: Given a
|
||||||
standard chessboard, place 8 queens such that no queen is in check from any
|
standard chess-board, place 8 queens such that no queen is in check from any
|
||||||
other (a queen can check another piece if they are on the same
|
other (a queen can check another piece if they are on the same
|
||||||
column, row, or diagional). We will now develop a solution to this
|
column, row, or diagonal). We will now develop a solution to this
|
||||||
problem, generalizing it to chessboards of arbitrary size. Hence, the
|
problem, generalizing it to chess-boards of arbitrary size. Hence, the
|
||||||
problem is to place $n$ queens on a chessboard of size $n \times n$.
|
problem is to place $n$ queens on a chess-board of size $n \times n$.
|
||||||
|
|
||||||
To solve this problem, note that we need to place a queen in each row.
|
To solve this problem, note that we need to place a queen in each row.
|
||||||
So we could place queens in successive rows, each time checking that a
|
So we could place queens in successive rows, each time checking that a
|
||||||
newly placed queen is not in queck from any other queens that have
|
newly placed queen is not in check from any other queens that have
|
||||||
already been placed. In the course of this search, it might arrive
|
already been placed. In the course of this search, it might arrive
|
||||||
that a queen to be placed in row $k$ would be in check in all fields
|
that a queen to be placed in row $k$ would be in check in all fields
|
||||||
of that row from queens in row $1$ to $k-1$. In that case, we need to
|
of that row from queens in row $1$ to $k-1$. In that case, we need to
|
||||||
|
@ -4006,7 +4006,7 @@ element for each solution.
|
||||||
Now, to place the $k$'the queen, we generate all possible extensions
|
Now, to place the $k$'the queen, we generate all possible extensions
|
||||||
of each previous solution by one more queen. This yields another list
|
of each previous solution by one more queen. This yields another list
|
||||||
of solution lists, this time of length $k$. We continue the process
|
of solution lists, this time of length $k$. We continue the process
|
||||||
until we have reached solutions of the size of the chessboard $n$.
|
until we have reached solutions of the size of the chess-board $n$.
|
||||||
This algorithmic idea is embodied in function \code{placeQueens} below:
|
This algorithmic idea is embodied in function \code{placeQueens} below:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
def queens(n: int): List[List[int]] = {
|
def queens(n: int): List[List[int]] = {
|
||||||
|
@ -4041,7 +4041,7 @@ Here is a small example database:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
val books: List[Book] = List(
|
val books: List[Book] = List(
|
||||||
Book("Structure and Interpretation of Computer Programs",
|
Book("Structure and Interpretation of Computer Programs",
|
||||||
List("Abelson, Harald", "Sussman, Gerald J.")),
|
List("Abelson, Harold", "Sussman, Gerald J.")),
|
||||||
Book("Principles of Compiler Design",
|
Book("Principles of Compiler Design",
|
||||||
List("Aho, Alfred", "Ullman, Jeffrey")),
|
List("Aho, Alfred", "Ullman, Jeffrey")),
|
||||||
Book("Programming in Modula-2",
|
Book("Programming in Modula-2",
|
||||||
|
@ -4184,7 +4184,7 @@ For-comprehensions resemble for-loops in imperative languages, except
|
||||||
that they produce a list of results. Sometimes, a list of results is
|
that they produce a list of results. Sometimes, a list of results is
|
||||||
not needed but we would still like the flexibility of generators and
|
not needed but we would still like the flexibility of generators and
|
||||||
filters in iterations over lists. This is made possible by a variant
|
filters in iterations over lists. This is made possible by a variant
|
||||||
of the for-comprehension syntax, which excpresses for-loops:
|
of the for-comprehension syntax, which expresses for-loops:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
for ( $s$ ) $e$
|
for ( $s$ ) $e$
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
@ -4270,7 +4270,7 @@ theory underlying functional programming.
|
||||||
|
|
||||||
In this chapter, we introduce functions with side effects and study
|
In this chapter, we introduce functions with side effects and study
|
||||||
their behavior. We will see that as a consequence we have to
|
their behavior. We will see that as a consequence we have to
|
||||||
fundamenatlly modify up the substitution model of computation which we
|
fundamentally modify up the substitution model of computation which we
|
||||||
employed so far.
|
employed so far.
|
||||||
|
|
||||||
\section{Stateful Objects}
|
\section{Stateful Objects}
|
||||||
|
@ -4308,7 +4308,7 @@ In Scala, every defined variable has to be initialized at the point of
|
||||||
its definition. For instance, the statement ~\code{var x: int;}~ is
|
its definition. For instance, the statement ~\code{var x: int;}~ is
|
||||||
{\em not} regarded as a variable definition, because the initializer
|
{\em not} regarded as a variable definition, because the initializer
|
||||||
is missing\footnote{If a statement like this appears in a class, it is
|
is missing\footnote{If a statement like this appears in a class, it is
|
||||||
instead regarded as a variable declaration, which introcuces
|
instead regarded as a variable declaration, which introduces
|
||||||
abstract access methods for the variable, but does not associate these
|
abstract access methods for the variable, but does not associate these
|
||||||
methods with a piece of state.}. If one does not know, or does not
|
methods with a piece of state.}. If one does not know, or does not
|
||||||
care about, the appropriate initializer, one can use a wildcard
|
care about, the appropriate initializer, one can use a wildcard
|
||||||
|
@ -4739,7 +4739,7 @@ inserts the pair \code{(curtime + delay, action)} into the
|
||||||
Pair(actiontime, action) :: ag
|
Pair(actiontime, action) :: ag
|
||||||
case (first @ Pair(time, act)) :: ag1 =>
|
case (first @ Pair(time, act)) :: ag1 =>
|
||||||
if (actiontime < time) Pair(actiontime, action) :: ag
|
if (actiontime < time) Pair(actiontime, action) :: ag
|
||||||
else first :: insert(ag1)
|
else first :: insert(ag1)
|
||||||
}
|
}
|
||||||
agenda = insert(agenda)
|
agenda = insert(agenda)
|
||||||
}
|
}
|
||||||
|
@ -4801,7 +4801,7 @@ sum 15 new_value = false
|
||||||
\section{Summary}
|
\section{Summary}
|
||||||
|
|
||||||
We have seen in this chapter the constructs that let us model state in
|
We have seen in this chapter the constructs that let us model state in
|
||||||
Scala -- these are variables, assignments, abd imperative control
|
Scala -- these are variables, assignments, and imperative control
|
||||||
structures. State and Assignment complicate our mental model of
|
structures. State and Assignment complicate our mental model of
|
||||||
computation. In particular, referential transparency is lost. On the
|
computation. In particular, referential transparency is lost. On the
|
||||||
other hand, assignment gives us new ways to formulate programs
|
other hand, assignment gives us new ways to formulate programs
|
||||||
|
@ -4812,8 +4812,8 @@ functional programming or programming with assignments works best.
|
||||||
|
|
||||||
The previous chapters have introduced variables, assignment and
|
The previous chapters have introduced variables, assignment and
|
||||||
stateful objects. We have seen how real-world objects that change
|
stateful objects. We have seen how real-world objects that change
|
||||||
with time can be modelled by changing the state of variables in a
|
with time can be modeled by changing the state of variables in a
|
||||||
computation. Time changes in the real world thus are modelled by time
|
computation. Time changes in the real world thus are modeled by time
|
||||||
changes in program execution. Of course, such time changes are usually
|
changes in program execution. Of course, such time changes are usually
|
||||||
stretched out or compressed, but their relative order is the same.
|
stretched out or compressed, but their relative order is the same.
|
||||||
This seems quite natural, but there is a also price to pay: Our simple
|
This seems quite natural, but there is a also price to pay: Our simple
|
||||||
|
@ -4822,7 +4822,7 @@ longer applicable once we introduce variables and assignment.
|
||||||
|
|
||||||
Is there another way? Can we model state change in the real world
|
Is there another way? Can we model state change in the real world
|
||||||
using only immutable functions? Taking mathematics as a guide, the
|
using only immutable functions? Taking mathematics as a guide, the
|
||||||
answer is clearly yes: A time-changing quantity is simply modelled by
|
answer is clearly yes: A time-changing quantity is simply modeled by
|
||||||
a function \code{f(t)} with a time parameter \code{t}. The same can be
|
a function \code{f(t)} with a time parameter \code{t}. The same can be
|
||||||
done in computation. Instead of overwriting a variable with successive
|
done in computation. Instead of overwriting a variable with successive
|
||||||
values, we represent all these values as successive elements in a
|
values, we represent all these values as successive elements in a
|
||||||
|
@ -4928,7 +4928,7 @@ This does not work for streams, where we require that the tail of a
|
||||||
stream should not be evaluated until it is demanded by a \code{tail} operation.
|
stream should not be evaluated until it is demanded by a \code{tail} operation.
|
||||||
The argument why list-append \code{:::} cannot be adapted to streams is analogous.
|
The argument why list-append \code{:::} cannot be adapted to streams is analogous.
|
||||||
|
|
||||||
Intstead of \code{x :: xs}, one uses \code{Stream.cons(x, xs)} for
|
Instead of \code{x :: xs}, one uses \code{Stream.cons(x, xs)} for
|
||||||
constructing a stream with first element \code{x} and (unevaluated)
|
constructing a stream with first element \code{x} and (unevaluated)
|
||||||
rest \code{xs}. Instead of \code{xs ::: ys}, one uses the operation
|
rest \code{xs}. Instead of \code{xs ::: ys}, one uses the operation
|
||||||
\code{xs append ys}.
|
\code{xs append ys}.
|
||||||
|
@ -4938,7 +4938,7 @@ rest \code{xs}. Instead of \code{xs ::: ys}, one uses the operation
|
||||||
Iterators are the imperative version of streams. Like streams,
|
Iterators are the imperative version of streams. Like streams,
|
||||||
iterators describe potentially infinite lists. However, there is no
|
iterators describe potentially infinite lists. However, there is no
|
||||||
data-structure which contains the elements of an iterator. Instead,
|
data-structure which contains the elements of an iterator. Instead,
|
||||||
iterators aloow one to step through the sequence, using two abstract methods \code{next} and \code{hasNext}.
|
iterators allow one to step through the sequence, using two abstract methods \code{next} and \code{hasNext}.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
trait Iterator[+a] {
|
trait Iterator[+a] {
|
||||||
def hasNext: boolean;
|
def hasNext: boolean;
|
||||||
|
@ -5035,7 +5035,7 @@ returns all elements of the original iterator that satisfy a criterion
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
In fact, \code{filter} returns instances of a subclass of iterators
|
In fact, \code{filter} returns instances of a subclass of iterators
|
||||||
which are ``buffered''. A \code{BufferedIterator} object is an
|
which are ``buffered''. A \code{BufferedIterator} object is an
|
||||||
interator which has in addition a method \code{head}. This method
|
iterator which has in addition a method \code{head}. This method
|
||||||
returns the element which would otherwise have been returned by
|
returns the element which would otherwise have been returned by
|
||||||
\code{head}, but does not advance beyond that element. Hence, the
|
\code{head}, but does not advance beyond that element. Hence, the
|
||||||
element returned by \code{head} is returned again by the next call to
|
element returned by \code{head} is returned again by the next call to
|
||||||
|
@ -6514,9 +6514,9 @@ class ComputeServer(n: Int) {
|
||||||
val reply = new SyncVar[a]();
|
val reply = new SyncVar[a]();
|
||||||
openJobs.write{
|
openJobs.write{
|
||||||
new Job {
|
new Job {
|
||||||
type t = a;
|
type t = a;
|
||||||
def task = p;
|
def task = p;
|
||||||
def ret(x: a) = reply.set(x);
|
def ret(x: a) = reply.set(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
() => reply.get
|
() => reply.get
|
||||||
|
@ -6604,7 +6604,7 @@ As a simple example of how mailboxes are used, consider a
|
||||||
one-place buffer:
|
one-place buffer:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
class OnePlaceBuffer {
|
class OnePlaceBuffer {
|
||||||
private val m = new MailBox; // An internal milbox
|
private val m = new MailBox; // An internal mailbox
|
||||||
private case class Empty, Full(x: int); // Types of messages we deal with
|
private case class Empty, Full(x: int); // Types of messages we deal with
|
||||||
m send Empty; // Initialization
|
m send Empty; // Initialization
|
||||||
def write(x: int): unit =
|
def write(x: int): unit =
|
||||||
|
@ -6662,10 +6662,10 @@ Otherwise, the message is appended to the linked list of sent messages.
|
||||||
if (s1 != null) {
|
if (s1 != null) {
|
||||||
s.next = s1.next; s1.elem
|
s.next = s1.next; s1.elem
|
||||||
} else {
|
} else {
|
||||||
val r = insert(lastReceiver, new Receiver {
|
val r = insert(lastReceiver, new Receiver {
|
||||||
def isDefined(msg: Any) = f.isDefinedAt(msg);
|
def isDefined(msg: Any) = f.isDefinedAt(msg);
|
||||||
});
|
});
|
||||||
lastReceiver = r;
|
lastReceiver = r;
|
||||||
r.elem.wait();
|
r.elem.wait();
|
||||||
r.elem.msg
|
r.elem.msg
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ varid ::= lower {letter $|$ digit} [`_' [id]]
|
||||||
id ::= upper {letter $|$ digit} [`_' [id]]
|
id ::= upper {letter $|$ digit} [`_' [id]]
|
||||||
| varid
|
| varid
|
||||||
| op
|
| op
|
||||||
| ```string chars`''
|
| ```string chars`''
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
There are three ways to form an identifier. First, an identifier can
|
There are three ways to form an identifier. First, an identifier can
|
||||||
|
@ -54,7 +54,7 @@ letters and digits. This may be followed by an underscore
|
||||||
themselves make up an identifier. Second, an identifier can be start
|
themselves make up an identifier. Second, an identifier can be start
|
||||||
with a special character followed by an arbitrary sequence of special
|
with a special character followed by an arbitrary sequence of special
|
||||||
characters. Finally, an identifier may also be formed by an arbitrary
|
characters. Finally, an identifier may also be formed by an arbitrary
|
||||||
string between backquotes (host systems may impose some restrictions
|
string between back-quotes (host systems may impose some restrictions
|
||||||
on which strings are legal for identifiers). As usual, a longest
|
on which strings are legal for identifiers). As usual, a longest
|
||||||
match rule applies. For instance, the string
|
match rule applies. For instance, the string
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ contravariant in their argument types.
|
||||||
\label{sec:synthetic-types}
|
\label{sec:synthetic-types}
|
||||||
|
|
||||||
The types explained in the following do not denote sets of values, nor
|
The types explained in the following do not denote sets of values, nor
|
||||||
do they appear explicitely in programs. They are introduced in this
|
do they appear explicitly in programs. They are introduced in this
|
||||||
report as the internal types of defined identifiers.
|
report as the internal types of defined identifiers.
|
||||||
|
|
||||||
\subsection{Method Types}
|
\subsection{Method Types}
|
||||||
|
@ -693,7 +693,7 @@ transitive relation that satisfies the following conditions.
|
||||||
one has $\mbox{\code{scala.AllRef}} \conforms T$.
|
one has $\mbox{\code{scala.AllRef}} \conforms T$.
|
||||||
\item A type variable or abstract type $t$ conforms to its upper bound and
|
\item A type variable or abstract type $t$ conforms to its upper bound and
|
||||||
its lower bound conforms to $t$.
|
its lower bound conforms to $t$.
|
||||||
\item A class type or parameterized type $c$ conforms to any of its basetypes, $b$.
|
\item A class type or parameterized type $c$ conforms to any of its base-types, $b$.
|
||||||
\item A type projection \lstinline@$T$#$t$@ conforms to \lstinline@$U$#$t$@ if
|
\item A type projection \lstinline@$T$#$t$@ conforms to \lstinline@$U$#$t$@ if
|
||||||
$T$ conforms to $U$.
|
$T$ conforms to $U$.
|
||||||
\item A parameterized type ~\lstinline@$T$[$T_1 \commadots T_n$]@~ conforms to
|
\item A parameterized type ~\lstinline@$T$[$T_1 \commadots T_n$]@~ conforms to
|
||||||
|
@ -767,7 +767,7 @@ class C extends A[C];
|
||||||
Then the types ~\lstinline@A[Any], A[A[Any]], A[A[A[Any]]], ...@~ form
|
Then the types ~\lstinline@A[Any], A[A[Any]], A[A[A[Any]]], ...@~ form
|
||||||
a descending sequence of upper bounds for \code{B} and \code{C}. The
|
a descending sequence of upper bounds for \code{B} and \code{C}. The
|
||||||
least upper bound would be the infinite limit of that sequence, which
|
least upper bound would be the infinite limit of that sequence, which
|
||||||
does ot exist as a Scala type. Since cases like this are in general
|
does not exist as a Scala type. Since cases like this are in general
|
||||||
impossible to detect, a Scala compiler is free to reject a term
|
impossible to detect, a Scala compiler is free to reject a term
|
||||||
which has a type specified as a least upper or greatest lower bound,
|
which has a type specified as a least upper or greatest lower bound,
|
||||||
and that bound would be more complex than some compiler-set
|
and that bound would be more complex than some compiler-set
|
||||||
|
@ -840,7 +840,7 @@ or \code{short} is always implicitly converted to a value of type
|
||||||
|
|
||||||
If an expression $e$ has type $T$ where $T$ does not conform to the
|
If an expression $e$ has type $T$ where $T$ does not conform to the
|
||||||
expected type $pt$ and $T$ has a member named \lstinline@coerce@ of type
|
expected type $pt$ and $T$ has a member named \lstinline@coerce@ of type
|
||||||
$[]U$ where $U$ does comform to $pt$, then the expression is typed and evaluated is if it was
|
$[]U$ where $U$ does conform to $pt$, then the expression is typed and evaluated is if it was
|
||||||
\lstinline@$e$.coerce@.
|
\lstinline@$e$.coerce@.
|
||||||
|
|
||||||
|
|
||||||
|
@ -877,7 +877,7 @@ s_n$, if a simple name in $s_i$ refers to an entity defined by $s_j$
|
||||||
where $j \geq i$, then every non-empty statement between and including
|
where $j \geq i$, then every non-empty statement between and including
|
||||||
$s_i$ and $s_j$ must be an import clause,
|
$s_i$ and $s_j$ must be an import clause,
|
||||||
or a function, type, class, or object definition. It may not be
|
or a function, type, class, or object definition. It may not be
|
||||||
a value definition, a variable defninition, or an expression.
|
a value definition, a variable definition, or an expression.
|
||||||
|
|
||||||
\comment{
|
\comment{
|
||||||
Every basic definition may introduce several defined names, separated
|
Every basic definition may introduce several defined names, separated
|
||||||
|
@ -914,7 +914,7 @@ the type definition
|
||||||
\comment{
|
\comment{
|
||||||
If an element in such a sequence introduces only the defined name,
|
If an element in such a sequence introduces only the defined name,
|
||||||
possibly with some type or value parameters, but leaves out any
|
possibly with some type or value parameters, but leaves out any
|
||||||
aditional parts in the definition, then those parts are implicitly
|
additional parts in the definition, then those parts are implicitly
|
||||||
copied from the next subsequent sequence element which consists of
|
copied from the next subsequent sequence element which consists of
|
||||||
more than just a defined name and parameters. Examples:
|
more than just a defined name and parameters. Examples:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
|
@ -1360,7 +1360,7 @@ The last value parameter of a parameter section may be suffixed by
|
||||||
if a method $m$ with type ~\lstinline@($T_1 \commadots T_n, S$*)$U$@~
|
if a method $m$ with type ~\lstinline@($T_1 \commadots T_n, S$*)$U$@~
|
||||||
is applied to arguments $(e_1 \commadots e_k)$ where $k \geq n$, then
|
is applied to arguments $(e_1 \commadots e_k)$ where $k \geq n$, then
|
||||||
$m$ is taken in that application to have type $(T_1 \commadots T_n, S
|
$m$ is taken in that application to have type $(T_1 \commadots T_n, S
|
||||||
\commadots S)U$, with $k - n$ occurences of type $S$.
|
\commadots S)U$, with $k - n$ occurrences of type $S$.
|
||||||
\todo{Change to ???: If the method
|
\todo{Change to ???: If the method
|
||||||
is converted to a function type instead of being applied immediately,
|
is converted to a function type instead of being applied immediately,
|
||||||
a repeated parameter \lstinline@$T$*@ is taken to be ~\lstinline@scala.Seq[$T$]@~
|
a repeated parameter \lstinline@$T$*@ is taken to be ~\lstinline@scala.Seq[$T$]@~
|
||||||
|
@ -1601,7 +1601,7 @@ class F extends B with D with E;
|
||||||
The mixin base classes and base classes of classes \code{A-F} are given in
|
The mixin base classes and base classes of classes \code{A-F} are given in
|
||||||
the following table:
|
the following table:
|
||||||
\begin{quote}\begin{tabular}{|l|l|l|} \hline
|
\begin{quote}\begin{tabular}{|l|l|l|} \hline
|
||||||
\ & Mixin base classses & Base classes \\ \hline
|
\ & Mixin base classes & Base classes \\ \hline
|
||||||
A & A & A, ScalaObject, AnyRef, Any \\
|
A & A & A, ScalaObject, AnyRef, Any \\
|
||||||
B & B & B, A, ScalaObject, AnyRef, Any \\
|
B & B & B, A, ScalaObject, AnyRef, Any \\
|
||||||
C & C & C, A, ScalaObject, AnyRef, Any \\
|
C & C & C, A, ScalaObject, AnyRef, Any \\
|
||||||
|
@ -1610,7 +1610,7 @@ E & C, D, E & E, B, C, D, A, ScalaObject, AnyRef, Any \\
|
||||||
F & C, D, E, F & F, B, D, E, C, A, ScalaObject, AnyRef, Any \\ \hline
|
F & C, D, E, F & F, B, D, E, C, A, ScalaObject, AnyRef, Any \\ \hline
|
||||||
\end{tabular}\end{quote}
|
\end{tabular}\end{quote}
|
||||||
Note that \code{D} is inherited twice by \code{F}, once directly, the
|
Note that \code{D} is inherited twice by \code{F}, once directly, the
|
||||||
other time indirectly throgh \code{E}. This is permitted, since
|
other time indirectly through \code{E}. This is permitted, since
|
||||||
\code{D} is a trait.
|
\code{D} is a trait.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1773,9 +1773,9 @@ labeled \code{protected}.
|
||||||
If $M'$ is not an abstract member, then
|
If $M'$ is not an abstract member, then
|
||||||
$M$ must be labeled \code{override}.
|
$M$ must be labeled \code{override}.
|
||||||
\item
|
\item
|
||||||
If $M'$ is labelled \code{abstract} and \code{override}, and $M'$ is a
|
If $M'$ is labeled \code{abstract} and \code{override}, and $M'$ is a
|
||||||
member of the static superclass of the class containing the definition
|
member of the static superclass of the class containing the definition
|
||||||
of $M$, then $M$ must also be labelled \code{abstract} and
|
of $M$, then $M$ must also be labeled \code{abstract} and
|
||||||
\code{override}.
|
\code{override}.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
|
@ -1852,11 +1852,11 @@ definition.
|
||||||
The \code{override} modifier has an additional significance when
|
The \code{override} modifier has an additional significance when
|
||||||
combined with the \code{abstract} modifier. That modifier combination
|
combined with the \code{abstract} modifier. That modifier combination
|
||||||
is only allowed for members of abstract classes. A member
|
is only allowed for members of abstract classes. A member
|
||||||
labelled \code{abstract} and \code{override} must override some
|
labeled \code{abstract} and \code{override} must override some
|
||||||
member of the superclass of the class containing the definition.
|
member of the superclass of the class containing the definition.
|
||||||
|
|
||||||
We call a member of a template {\em incomplete} if it is either
|
We call a member of a template {\em incomplete} if it is either
|
||||||
abstract (i.e.\ defined by a declaration), or it is labelled
|
abstract (i.e.\ defined by a declaration), or it is labeled
|
||||||
\code{abstract} and \code{override} and it overrides an incomplete
|
\code{abstract} and \code{override} and it overrides an incomplete
|
||||||
member of the template's superclass.
|
member of the template's superclass.
|
||||||
|
|
||||||
|
@ -2030,7 +2030,7 @@ This defines a class \code{LinkedList} with an overloaded constructor of type
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
[a](): LinkedList[a] $\overload$
|
[a](): LinkedList[a] $\overload$
|
||||||
[a](x: a): LinkedList[a] $\overload$
|
[a](x: a): LinkedList[a] $\overload$
|
||||||
[a](x: a, xs: LinkList[a]): LinkedList[a] .
|
[a](x: a, xs: LinkedList[a]): LinkedList[a] .
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
The second constructor alternative constructs an singleton list, while the
|
The second constructor alternative constructs an singleton list, while the
|
||||||
third one constructs a list with a given head and tail.
|
third one constructs a list with a given head and tail.
|
||||||
|
@ -3779,7 +3779,7 @@ abstract sealed class Long extends AnyVal {
|
||||||
def coerce: Float // convert to Float
|
def coerce: Float // convert to Float
|
||||||
|
|
||||||
def + (that: Double): Double; // double addition
|
def + (that: Double): Double; // double addition
|
||||||
def + (that: Float): Double; // float addtion
|
def + (that: Float): Double; // float addition
|
||||||
def + (that: Long): Long = // long addition
|
def + (that: Long): Long = // long addition
|
||||||
/* analogous for -, *, /, % */
|
/* analogous for -, *, /, % */
|
||||||
|
|
||||||
|
@ -3935,7 +3935,7 @@ case class Tuple$n$[+a_1, ..., +a_n](_1: a_1, ..., _$n$: a_$n$) {
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
The implicity imported \code{Predef} object (\sref{cls:predef}) defines
|
The implicitly imported \code{Predef} object (\sref{cls:predef}) defines
|
||||||
the names \code{Pair} as an alias of \code{Tuple2} and \code{Triple}
|
the names \code{Pair} as an alias of \code{Tuple2} and \code{Triple}
|
||||||
as an alias for \code{Tuple3}.
|
as an alias for \code{Tuple3}.
|
||||||
|
|
||||||
|
@ -3979,7 +3979,7 @@ class PartialFunction[-a,+b] extends Function1[a, b] {
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
The implicity imported \code{Predef} object (\sref{cls:predef}) defines the name
|
The implicitly imported \code{Predef} object (\sref{cls:predef}) defines the name
|
||||||
\code{Function} as an alias of \code{Function1}.
|
\code{Function} as an alias of \code{Function1}.
|
||||||
|
|
||||||
\subsection{Class \large{\code{Array}}}\label{cls:array}
|
\subsection{Class \large{\code{Array}}}\label{cls:array}
|
||||||
|
@ -4019,7 +4019,7 @@ module Array {
|
||||||
\section{The \large{\code{Predef}} Object}\label{cls:predef}
|
\section{The \large{\code{Predef}} Object}\label{cls:predef}
|
||||||
|
|
||||||
The \code{Predef} module defines standard functions and type aliases
|
The \code{Predef} module defines standard functions and type aliases
|
||||||
for Scala programs. It is always implicity imported, so that all its
|
for Scala programs. It is always implicitly imported, so that all its
|
||||||
defined members are available without qualification. Here is its
|
defined members are available without qualification. Here is its
|
||||||
definition for the JVM environment.
|
definition for the JVM environment.
|
||||||
|
|
||||||
|
@ -4076,504 +4076,3 @@ object Predef {
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
\appendix
|
|
||||||
\chapter{Scala Syntax Summary}
|
|
||||||
|
|
||||||
The lexical syntax of Scala is given by the following grammar in EBNF
|
|
||||||
form.
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
upper ::= `A' | $\ldots$ | `Z' | `$\Dollar$' | `_'
|
|
||||||
lower ::= `a' | $\ldots$ | `z'
|
|
||||||
letter ::= upper | lower
|
|
||||||
digit ::= `0' | $\ldots$ | `9'
|
|
||||||
special ::= $\mbox{\rm\em ``all other characters except parentheses ([{}]) and periods''}$
|
|
||||||
|
|
||||||
op ::= special {special}
|
|
||||||
varid ::= lower {letter | digit} [`_' [id]]
|
|
||||||
id ::= upper {letter | digit} [`_' [id]]
|
|
||||||
| varid
|
|
||||||
| op
|
|
||||||
| `\'stringLit
|
|
||||||
|
|
||||||
intLit ::= $\mbox{\rm\em ``as in Java''}$
|
|
||||||
floatLit ::= $\mbox{\rm\em ``as in Java''}$
|
|
||||||
charLit ::= $\mbox{\rm\em ``as in Java''}$
|
|
||||||
stringLit ::= $\mbox{\rm\em ``as in Java''}$
|
|
||||||
symbolLit ::= `\'' id
|
|
||||||
|
|
||||||
comment ::= `/*' ``any sequence of characters'' `*/'
|
|
||||||
| `//' `any sequence of characters up to end of line''
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
The context-free syntax of Scala is given by the following EBNF
|
|
||||||
grammar.
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
Literal ::= intLit
|
|
||||||
| floatLit
|
|
||||||
| charLit
|
|
||||||
| stringLit
|
|
||||||
| symbolLit
|
|
||||||
| true
|
|
||||||
| false
|
|
||||||
| null
|
|
||||||
|
|
||||||
StableId ::= id
|
|
||||||
| Path `.' id
|
|
||||||
Path ::= StableId
|
|
||||||
| [id `.'] this
|
|
||||||
| [id '.'] super [`[' id `]']`.' id
|
|
||||||
|
|
||||||
Type ::= Type1 `=>' Type
|
|
||||||
| `(' [Types] `)' `=>' Type
|
|
||||||
| Type1
|
|
||||||
Type1 ::= SimpleType {with SimpleType} [Refinement]
|
|
||||||
SimpleType ::= SimpleType TypeArgs
|
|
||||||
| SimpleType `#' id
|
|
||||||
| StableId
|
|
||||||
| Path `.' type
|
|
||||||
| `(' Type ')'
|
|
||||||
TypeArgs ::= `[' Types `]'
|
|
||||||
Types ::= Type {`,' Type}
|
|
||||||
Refinement ::= `{' [RefineStat {`;' RefineStat}] `}'
|
|
||||||
RefineStat ::= Dcl
|
|
||||||
| type TypeDef {`,' TypeDef}
|
|
||||||
|
|
|
||||||
|
|
||||||
Exprs ::= Expr {`,' Expr}
|
|
||||||
Expr ::= Bindings `=>' Expr
|
|
||||||
| Expr1
|
|
||||||
Expr1 ::= if `(' Expr1 `)' Expr [[`;'] else Expr]
|
|
||||||
| try `{' Block `}' [catch Expr] [finally Expr]
|
|
||||||
| do Expr [`;'] while `(' Expr ')'
|
|
||||||
| for `(' Enumerators `)' (do | yield) Expr
|
|
||||||
| return [Expr]
|
|
||||||
| throw Expr
|
|
||||||
| [SimpleExpr `.'] id `=' Expr
|
|
||||||
| SimpleExpr ArgumentExprs `=' Expr
|
|
||||||
| PostfixExpr [`:' Type1]
|
|
||||||
PostfixExpr ::= InfixExpr [id]
|
|
||||||
InfixExpr ::= PrefixExpr
|
|
||||||
| InfixExpr id PrefixExpr
|
|
||||||
PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr
|
|
||||||
SimpleExpr ::= Literal
|
|
||||||
| Path
|
|
||||||
| `(' [Expr] `)'
|
|
||||||
| BlockExpr
|
|
||||||
| new Template
|
|
||||||
| SimpleExpr `.' id
|
|
||||||
| SimpleExpr TypeArgs
|
|
||||||
| SimpleExpr ArgumentExprs
|
|
||||||
ArgumentExprs ::= `(' [Exprs] ')'
|
|
||||||
| BlockExpr
|
|
||||||
BlockExpr ::= `{' CaseClause {CaseClause} `}'
|
|
||||||
| `{' Block `}'
|
|
||||||
Block ::= {BlockStat `;'} [ResultExpr]
|
|
||||||
BlockStat ::= Import
|
|
||||||
| Def
|
|
||||||
| {LocalModifier} ClsDef
|
|
||||||
| Expr1
|
|
||||||
|
|
|
||||||
ResultExpr ::= Expr1
|
|
||||||
| Bindings `=>' Block
|
|
||||||
|
|
||||||
Enumerators ::= Generator {`;' Enumerator}
|
|
||||||
Enumerator ::= Generator
|
|
||||||
| Expr
|
|
||||||
Generator ::= val Pattern1 `<-' Expr
|
|
||||||
|
|
||||||
CaseClause ::= case Pattern [`if' PostfixExpr] `=>' Block
|
|
||||||
|
|
||||||
Constr ::= StableId [TypeArgs] [`(' [Exprs] `)']
|
|
||||||
|
|
||||||
Pattern ::= Pattern1 { `|' Pattern1 }
|
|
||||||
Pattern1 ::= varid `:' Type
|
|
||||||
| `_' `:' Type
|
|
||||||
| Pattern2
|
|
||||||
Pattern2 ::= [varid `@'] Pattern3
|
|
||||||
Pattern3 ::= SimplePattern [ '*' | '?' | '+' ]
|
|
||||||
| SimplePattern { id SimplePattern }
|
|
||||||
SimplePattern ::= `_'
|
|
||||||
| varid
|
|
||||||
| Literal
|
|
||||||
| StableId [ `(' [Patterns] `)' ]
|
|
||||||
| `(' [Patterns] `)'
|
|
||||||
Patterns ::= Pattern {`,' Pattern}
|
|
||||||
|
|
||||||
TypeParamClause ::= `[' TypeParam {`,' TypeParam} `]'
|
|
||||||
FunTypeParamClause ::= `[' TypeDcl {`,' TypeDcl} `]'
|
|
||||||
TypeParam ::= [`+' | `-'] TypeDcl
|
|
||||||
ParamClause ::= `(' [Param {`,' Param}] `)'
|
|
||||||
Param ::= [def] id `:' Type [`*']
|
|
||||||
Bindings ::= id [`:' Type1]
|
|
||||||
| `(' Binding {`,' Binding `)'
|
|
||||||
Binding ::= id [`:' Type]
|
|
||||||
|
|
||||||
Modifier ::= LocalModifier
|
|
||||||
| private
|
|
||||||
| protected
|
|
||||||
| override
|
|
||||||
LocalModifier ::= abstract
|
|
||||||
| final
|
|
||||||
| sealed
|
|
||||||
|
|
||||||
Template ::= Constr {`with' Constr} [TemplateBody]
|
|
||||||
TemplateBody ::= `{' [TemplateStat {`;' TemplateStat}] `}'
|
|
||||||
TemplateStat ::= Import
|
|
||||||
| {Modifier} Def
|
|
||||||
| {Modifier} Dcl
|
|
||||||
| Expr
|
|
||||||
|
|
|
||||||
|
|
||||||
Import ::= import ImportExpr {`,' ImportExpr}
|
|
||||||
ImportExpr ::= StableId `.' (id | `_' | ImportSelectors)
|
|
||||||
ImportSelectors ::= `{' {ImportSelector `,'}
|
|
||||||
(ImportSelector | `_') `}'
|
|
||||||
ImportSelector ::= id [`=>' id | `=>' `_']
|
|
||||||
|
|
||||||
Dcl ::= val ValDcl {`,' ValDcl}
|
|
||||||
| var VarDcl {`,' VarDcl}
|
|
||||||
| def FunDcl {`,' FunDcl}
|
|
||||||
| type TypeDcl {`,' TypeDcl}
|
|
||||||
ValDcl ::= id `:' Type
|
|
||||||
VarDcl ::= id `:' Type
|
|
||||||
FunDcl ::= id [FunTypeParamClause] {ParamClause} `:' Type
|
|
||||||
TypeDcl ::= id [`>:' Type] [`<:' Type]
|
|
||||||
|
|
||||||
Def ::= val PatDef {`,' PatDef}
|
|
||||||
| var VarDef {`,' VarDef}
|
|
||||||
| def FunDef {`,' FunDef}
|
|
||||||
| type TypeDef {`,' TypeDef}
|
|
||||||
| ClsDef
|
|
||||||
PatDef ::= Pattern `=' Expr
|
|
||||||
VarDef ::= id [`:' Type] `=' Expr
|
|
||||||
| id `:' Type `=' `_'
|
|
||||||
FunDef ::= id [FunTypeParamClause] {ParamClause}
|
|
||||||
[`:' Type] `=' Expr
|
|
||||||
| this ParamClause `=' ConstrExpr
|
|
||||||
TypeDef ::= id [TypeParamClause] `=' Type
|
|
||||||
ClsDef ::= ([case] class | trait) ClassDef {`,' ClassDef}
|
|
||||||
| [case] object ObjectDef {`,' ObjectDef}
|
|
||||||
ClassDef ::= id [TypeParamClause] [ParamClause]
|
|
||||||
[`:' SimpleType] ClassTemplate
|
|
||||||
ObjectDef ::= id [`:' SimpleType] ClassTemplate
|
|
||||||
ClassTemplate ::= extends Template
|
|
||||||
| TemplateBody
|
|
||||||
|
|
|
||||||
ConstrExpr ::= this ArgumentExprs
|
|
||||||
| `{' this ArgumentExprs {`;' BlockStat} `}'
|
|
||||||
|
|
||||||
CompilationUnit ::= [package QualId `;'] {TopStat `;'} TopStat
|
|
||||||
TopStat ::= {Modifier} ClsDef
|
|
||||||
| Import
|
|
||||||
| Packaging
|
|
||||||
|
|
|
||||||
Packaging ::= package QualId `{' {TopStat `;'} TopStat `}'
|
|
||||||
QualId ::= id {`.' id}
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
\chapter{Implementation Status}
|
|
||||||
|
|
||||||
The present Scala compiler does not yet implement all of the Scala
|
|
||||||
specification. Its currently existing omissions and deviations are
|
|
||||||
listed below. We are working on a refined implementation that
|
|
||||||
addresses these issues.
|
|
||||||
\begin{enumerate}
|
|
||||||
\item
|
|
||||||
Unicode support is still limited. At present we only permit Unicode
|
|
||||||
encodings \verb@\uXXXX@ in strings and backquote-enclosed identifiers.
|
|
||||||
To define or access a Unicode identifier, you need to put it in
|
|
||||||
backquotes and use the \verb@\uXXXX@ encoding.
|
|
||||||
\item
|
|
||||||
The unicode operator ``$\Rightarrow$''
|
|
||||||
(\sref{sec:idents}) is not yet recognized; you need to use the two
|
|
||||||
character ASCII equivalent ``\code{=>}'' instead.
|
|
||||||
\item
|
|
||||||
The current implementation does not yet support run-time types.
|
|
||||||
All types are erased (\sref{sec:erasure}) during compilation. This means that
|
|
||||||
the following operations give potentially wrong results.
|
|
||||||
\begin{itemize}
|
|
||||||
\item
|
|
||||||
Type tests and type casts to parameterized types. Here it is only tested
|
|
||||||
that a value is an instance of the given top-level type constructor.
|
|
||||||
\item
|
|
||||||
Type tests and type casts to type parameters and abstract types. Here
|
|
||||||
it is only tested that a value is an instance of the type parameter's upper bound.
|
|
||||||
\item
|
|
||||||
Polymorphic array creation. If \code{t} is a type variable or abstract type, then
|
|
||||||
\code{new Array[t]} will yield an array of the upper bound of \code{t}.
|
|
||||||
\end{itemize}
|
|
||||||
\item
|
|
||||||
Return expressions are not yet permitted inside an anonymous function
|
|
||||||
or inside a call-by-name argument (i.e.\ a function argument corresponding to a
|
|
||||||
\code{def} parameter).
|
|
||||||
\item
|
|
||||||
Members of the empty package (\sref{sec:packagings}) cannot yet be
|
|
||||||
accessed from other source files. Hence, all library classes and
|
|
||||||
objects have to be in some package.
|
|
||||||
\item
|
|
||||||
At present, auxiliary constructors (\sref{sec:constr-defs}) are only permitted
|
|
||||||
for monomorphic classes.
|
|
||||||
\item
|
|
||||||
The \code{Array} class supports as yet only a restricted set of
|
|
||||||
operations as given in \sref{cls:array}. It is planned to extend that
|
|
||||||
interface. In particular, arrays will implement the \code{scala.Seq}
|
|
||||||
trait as well as the methods needed to support for-comprehensions.
|
|
||||||
\item
|
|
||||||
At present, all classes used as mixins must be accessible to the Scala
|
|
||||||
compiler in source form.
|
|
||||||
\end{enumerate}
|
|
||||||
|
|
||||||
\end{document}
|
|
||||||
|
|
||||||
|
|
||||||
\comment{
|
|
||||||
\section{Definitions}
|
|
||||||
|
|
||||||
For a possibly recursive definition such as $\LET;x_1 = e_1
|
|
||||||
;\ldots; \LET x_n = e_n$, local type inference proceeds as
|
|
||||||
follows.
|
|
||||||
A first phase assigns {\em a-priori types} to the $x_i$. The a-priori
|
|
||||||
type of $x$ is the declared type of $x$ if a declared type is
|
|
||||||
given. Otherwise, it is the inherited type, if one is
|
|
||||||
given. Otherwise, it is undefined.
|
|
||||||
|
|
||||||
A second phase assigns completely defined types to the $x_i$, in some
|
|
||||||
order. The type of $x$ is the a-priori type, if it is completely
|
|
||||||
defined. Otherwise, it is the a-priori type of $x$'s right hand side.
|
|
||||||
The a-priori type of an expression $e$ depends on the form of $e$.
|
|
||||||
\begin{enumerate}
|
|
||||||
\item
|
|
||||||
The a-priori type of a
|
|
||||||
typed expression $e:T$ is $T$.
|
|
||||||
\item
|
|
||||||
The a-priori type of a class instance
|
|
||||||
creation expression $c;\WITH;(b)$ is $C;\WITH;R$ where $C$ is the
|
|
||||||
type of the class given in $c$ and $R$ is the a-priori type of block
|
|
||||||
$b$.
|
|
||||||
\item
|
|
||||||
The a-priori type of a block is a record consisting the a-priori
|
|
||||||
types of each non-private identifier which is declared in the block
|
|
||||||
and which is visible at in last statement of the block. Here, it is
|
|
||||||
required that every import clause $\IMPORT;e_1 \commadots e_n$ refers
|
|
||||||
to expressions whose type can be computed with the type information
|
|
||||||
determined so far. Otherwise, a compile time error results.
|
|
||||||
\item
|
|
||||||
The a-priori type of any other expression is the expression's type, if
|
|
||||||
that type can be computed with the type information determined so far.
|
|
||||||
Otherwise, a compile time error results.
|
|
||||||
\end{enumerate}
|
|
||||||
The compiler will find an ordering in which types are assigned without
|
|
||||||
compiler errors to all variables $x_1 \commadots x_n$, if such an
|
|
||||||
ordering exists. This can be achieved by lazy evaluation.
|
|
||||||
}
|
|
||||||
\section{Exceptions}
|
|
||||||
\label{sec:exceptions}
|
|
||||||
|
|
||||||
There is a predefined type \code{Throwable}, as well as functions to
|
|
||||||
throw and handle values of type \code{Throwable}. These are declared
|
|
||||||
as follows.
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
class Throwable {
|
|
||||||
def throw[a]: a
|
|
||||||
}
|
|
||||||
class ExceptOrFinally[a] {
|
|
||||||
def except (handler: PartialFunction[Throwable,a]): a
|
|
||||||
def finally (def handler: Unit): a
|
|
||||||
}
|
|
||||||
def try [a] (def body: a): ExceptOrFinally[a]
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
The type \code{Throwable} represents exceptions and error objects; it
|
|
||||||
may be identified with an analogous type of the underlying
|
|
||||||
implementation such as \code{java.lang.Throwable}. We will in the
|
|
||||||
following loosely call values of type \code{Throwable} exceptions.
|
|
||||||
|
|
||||||
The \code{throw} method in \code{Throwable} aborts execution of the
|
|
||||||
thread executing it and passes the thrown exception to the handler
|
|
||||||
that was most recently installed by a
|
|
||||||
\code{try} function in the current thread. If no \code{try} method is
|
|
||||||
active, the thread terminates.
|
|
||||||
|
|
||||||
The \code{try} function executes its body with the given exception
|
|
||||||
handler. A \code{try} expression comes in two forms. The first form is
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
try $body$ except $handler$ .
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
If $body$ executes without an exception being thrown, then executing
|
|
||||||
the try expression is equivalent to just executing $body$. If some
|
|
||||||
exception is thrown from within $body$ for which \code{handler} is defined,
|
|
||||||
the handler is invoked with the thrown exception as argument.
|
|
||||||
|
|
||||||
The second form of a try expression is
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
try $body$ finally $handler$ .
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
This expression will execute $body$. A normal execution of $body$ is
|
|
||||||
followed by an invocation of the $handler$ expression. The $handler$
|
|
||||||
expression does not take arguments and has \code{Unit} as result type.
|
|
||||||
If execution of the handler expression throws an exception, this
|
|
||||||
exception is propagated out of the \code{try} statement. Otherwise,
|
|
||||||
if an exception was thrown in $body$ prior to invocation of $handler$,
|
|
||||||
that exception is re-thrown after the invocation. Finally, if both
|
|
||||||
$body$ and $handler$ terminate normally, the original result of
|
|
||||||
$body$ is the result of the \code{try} expression.
|
|
||||||
|
|
||||||
\example An example of a try-except expression:
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
try {
|
|
||||||
System.in.readString()
|
|
||||||
} except {
|
|
||||||
case ex: EndOfFile => ""
|
|
||||||
}
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
\example An example of a try-finally expression:
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
file = open (fileName)
|
|
||||||
if (file != null) {
|
|
||||||
try {
|
|
||||||
process (file)
|
|
||||||
} finally {
|
|
||||||
file.close
|
|
||||||
}
|
|
||||||
}
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
\section{Concurrency}
|
|
||||||
\label{sec:concurrency}
|
|
||||||
|
|
||||||
\subsection{Basic Concurrency Constructs}
|
|
||||||
|
|
||||||
Scala programs may be executed by several threads that operate
|
|
||||||
concurrently. The thread model used is based on the model of the
|
|
||||||
underlying run-time system. We postulate a predefined
|
|
||||||
class \code{Thread} for run-time threads,
|
|
||||||
\code{fork} function to spawn off a new thread,
|
|
||||||
as well as \code{Monitor} and \code{Signal} classes. These are
|
|
||||||
specified as follows\notyet{Concurrency constructs are}.
|
|
||||||
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
class Thread { $\ldots$ }
|
|
||||||
def fork (def p: Unit): Thread
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
The \code{fork} function runs its argument computation \code{p} in a
|
|
||||||
separate thread. It returns the thread object immediately to its
|
|
||||||
caller. Unhandled exceptions (\sref{sec:exceptions}) thrown during
|
|
||||||
evaluation of \code{p} abort execution of the forked thread and are
|
|
||||||
otherwise ignored.
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
class Monitor {
|
|
||||||
def synchronized [a] (def e: a): a
|
|
||||||
}
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
Monitors define a \code{synchronized} method which provides mutual
|
|
||||||
exclusion between threads. It executes its argument computation
|
|
||||||
\code{e} while asserting exclusive ownership of the monitor
|
|
||||||
object whose method is invoked. If some other thread has ownership of
|
|
||||||
the same monitor object, the computation is delayed until the other
|
|
||||||
process has relinquished its ownership. Ownership of a monitor is
|
|
||||||
relinquished at the end of the argument computation, and while the
|
|
||||||
computation is waiting for a signal.
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
class Signal {
|
|
||||||
def wait: Unit
|
|
||||||
def wait(msec: Long): Unit
|
|
||||||
def notify: Unit
|
|
||||||
def notifyAll: Unit
|
|
||||||
}
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
The \code{Signal} class provides the basic means for process
|
|
||||||
synchronization. The \code{wait} method of a signal suspends the
|
|
||||||
calling thread until it is woken up by some future invocation of the
|
|
||||||
signal's \code{notify} or \code{notifyAll} method. The \code{notify}
|
|
||||||
method wakes up one thread that is waiting for the signal. The
|
|
||||||
\code{notifyAll} method wakes up all threads that are waiting for the
|
|
||||||
signal. A second version of the \code{wait} method takes a time-out
|
|
||||||
parameter (given in milliseconds). A thread calling \code{wait(msec)}
|
|
||||||
will suspend until unblocked by a \code{notify} or \code{notifyAll}
|
|
||||||
method, or until the \code{msec} millseconds have passed.
|
|
||||||
|
|
||||||
\subsection{Channels}
|
|
||||||
|
|
||||||
\begin{lstlisting}
|
|
||||||
class Channel[a] {
|
|
||||||
def write(x: a): Unit
|
|
||||||
def read: a
|
|
||||||
}
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
An object of type \code{Channel[a]} Channels offer a write-operation
|
|
||||||
which writes data of type \code{a} to the channel, and a read
|
|
||||||
operation, which returns written data as a result. The write operation
|
|
||||||
is non-blocking; that is it returns immediately without waiting for
|
|
||||||
the written data to be read.
|
|
||||||
|
|
||||||
\subsection{Message Spaces}
|
|
||||||
|
|
||||||
The Scala library also provides message spaces as a higher-level,
|
|
||||||
flexible construct for process synchronization and communication. A
|
|
||||||
{\em message} is an arbitrary object that inherits from the
|
|
||||||
\code{Message} class.
|
|
||||||
There is a special message \code{TIMEOUT} which is used to signal a time-out.
|
|
||||||
\begin{lstlisting}
|
|
||||||
class Message
|
|
||||||
case class TIMEOUT extends Message
|
|
||||||
\end{lstlisting}
|
|
||||||
Message spaces implement the following class.
|
|
||||||
\begin{lstlisting}
|
|
||||||
class MessageSpace {
|
|
||||||
def send(msg: Message): Unit
|
|
||||||
def receive[a](f: PartialFunction1[Message, a]): a
|
|
||||||
def receiveWithin[a](msec: Long)(f: PartialFunction1[Message, a]): a
|
|
||||||
}
|
|
||||||
\end{lstlisting}
|
|
||||||
The state of a message space consists of a multi-set of messages.
|
|
||||||
Messages are added to the space using the \code{send} method. Messages
|
|
||||||
are removed using the \code{receive} method, which is passed a message
|
|
||||||
processor \code{f} as argument, which is a partial function from
|
|
||||||
messages to some arbitrary result type. Typically, this function is
|
|
||||||
implemented as a pattern matching expression. The \code{receive}
|
|
||||||
method blocks until there is a message in the space for which its
|
|
||||||
message processor is defined. The matching message is then removed
|
|
||||||
from the space and the blocked thread is restarted by applying the
|
|
||||||
message processor to the message. Both sent messages and receivers are
|
|
||||||
ordered in time. A receiver $r$ is applied to a matching message $m$
|
|
||||||
only if there is no other (message, receiver) pair which precedes $(m,
|
|
||||||
r)$ in the partial ordering on pairs that orders each component in
|
|
||||||
time.
|
|
||||||
|
|
||||||
The message space class also offers a method \code{receiveWithin}
|
|
||||||
which blocks for only a specified maximal amount of time. If no
|
|
||||||
message is received within the specified time interval (given in
|
|
||||||
milliseconds), the message processor argument $f$ will be unblocked
|
|
||||||
with the special \code{TIMEOUT} message.
|
|
||||||
|
|
||||||
case class extends { $\ldots$ }
|
|
||||||
|
|
||||||
trait List { }
|
|
||||||
class Nil
|
|
||||||
class Cons
|
|
||||||
|
|
||||||
\comment{changes:
|
|
||||||
Type ::= SimpleType {with SimpleType} [with Refinement]
|
|
||||||
| class SimpleType
|
|
||||||
SimpleType ::= SimpleType [TypeArgs]
|
|
||||||
| `(' [Types] `)'
|
|
||||||
|
|
|
||||||
| this
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,7 +22,5 @@ Martin Odersky
|
||||||
|
|
||||||
\input{RationalePart}
|
\input{RationalePart}
|
||||||
|
|
||||||
\bibliographystyle{alpha}
|
|
||||||
\bibliography{Scala}
|
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
|
@ -93,9 +93,12 @@ Matthias Zenger \\[25mm]\ }
|
||||||
\input{RationalePart}
|
\input{RationalePart}
|
||||||
|
|
||||||
\part{The Scala Language Specification}
|
\part{The Scala Language Specification}
|
||||||
|
|
||||||
\input{ReferencePart}
|
\input{ReferencePart}
|
||||||
|
|
||||||
\bibliographystyle{alpha}
|
\bibliographystyle{alpha}
|
||||||
\bibliography{Scala}
|
\bibliography{Scala}
|
||||||
|
|
||||||
|
\input{ReferencePartAppendix}
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|
|
@ -96,6 +96,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
|
||||||
}
|
}
|
||||||
|
|
||||||
def lateEnter(unit: Unit, sym: Symbol): unit = {
|
def lateEnter(unit: Unit, sym: Symbol): unit = {
|
||||||
|
//System.out.println("late enter: " + sym + " " + sym.isModule());//DEBUG
|
||||||
enterUnit(unit);
|
enterUnit(unit);
|
||||||
if (sym.rawFirstInfo().isInstanceOf[SourceCompleter]) {
|
if (sym.rawFirstInfo().isInstanceOf[SourceCompleter]) {
|
||||||
sym.setInfo(Type.ErrorType);
|
sym.setInfo(Type.ErrorType);
|
||||||
|
|
|
@ -2,14 +2,14 @@ bug95.scala:1: illegal inheritance from sealed class
|
||||||
class C extends AnyVal;
|
class C extends AnyVal;
|
||||||
^
|
^
|
||||||
bug95.scala:1: illegal inheritance;
|
bug95.scala:1: illegal inheritance;
|
||||||
scala.AnyVal does not conform to scala.ScalaObject's supertype
|
scala.AnyVal does not conform to scala.ScalaObject's supertype java.lang.Object
|
||||||
class C extends AnyVal;
|
class C extends AnyVal;
|
||||||
^
|
^
|
||||||
bug95.scala:2: illegal inheritance from sealed class
|
bug95.scala:2: illegal inheritance from sealed class
|
||||||
class T extends Unit;
|
class T extends Unit;
|
||||||
^
|
^
|
||||||
bug95.scala:2: illegal inheritance;
|
bug95.scala:2: illegal inheritance;
|
||||||
scala.Unit does not conform to scala.ScalaObject's supertype
|
scala.Unit does not conform to scala.ScalaObject's supertype java.lang.Object
|
||||||
class T extends Unit;
|
class T extends Unit;
|
||||||
^
|
^
|
||||||
four errors found
|
four errors found
|
||||||
|
|
Loading…
Reference in New Issue