*** 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:
odersky 2004-01-20 11:50:36 +00:00
parent cf69c6449c
commit bcfd151a69
6 changed files with 77 additions and 576 deletions

View File

@ -23,8 +23,8 @@ interesting programming techniques. The present informal exposition is
meant to be complemented by the Java Language Reference Manual which
specifies Scala in a more detailed and precise way.
\paragraph{Acknowledgement}
We owe a great dept to Sussman and Abelson's wonderful book
\paragraph{Acknowledgment}
We owe a great debt to Abelson's and Sussman's wonderful book
``Structure and Interpretation of Computer
Programs''\cite{abelson-sussman:structure}. Many of their examples and
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.
\end{itemize}
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
because it is one of the things that makes it easy to combine Scala
components with components written in mainstream languages such as
@ -106,7 +106,7 @@ def sort(xs: List[int]): List[int] = {
\end{lstlisting}
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
\code{filter} and \code{:::}.}
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 Partition the lists into two sub-lists containing elements that
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
the sort function.\footnote{This is not quite what the imperative algorithm does;
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}
The process behavior is defined by its \code{run} method. That method
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
determined by the \code{timeToShutdown} constant and replies to
further offers that the auction is closed.
@ -632,7 +632,7 @@ def sqrtIter(guess: double, x: double): double =
else sqrtIter(improve(guess, x), x);
\end{lstlisting}
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.
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;
\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}.
\begin{lstlisting}
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
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
is not tail-recursive; it needs space proportional to its input
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,
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
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
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
@ -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
outside class \code{Rational}. They are used in the implementation of
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.
\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
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
return true if the set \code{s} contains the element \code{x}, and
should return \code{false} otherwise. The interface of such sets is
@ -1750,7 +1750,7 @@ trait Nat {
def - (that: Nat): Nat;
}
\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{N} is represented as \code{N} applications of the \code{Succ}
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))
\end{lstlisting}
\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
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
@ -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
address, which is what the as the default implementation of \code{hashCode} does.
\item
Case classes implicity come with nullary accessor methods which
Case classes implicitly come with nullary accessor methods which
retrieve the constructor arguments.
In our example, \code{Number} would obtain an accessor method
\begin{lstlisting}
@ -2418,7 +2418,7 @@ val s = new EmptySet[java.io.File]
$\mbox{\sl parameter bound}$ Ord[java.io.File].
\end{lstlisting}
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}
package scala;
trait Ord[t <: Ord[t]]: t {
@ -2519,7 +2519,7 @@ class Array[+a] {
$\mbox{\sl appears in contravariant position.}$
}
\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}
potentially changes state, and therefore undermines the soundness of
co-variant subtyping.
@ -2580,7 +2580,7 @@ often suggest a useful generalization of the contested method.
\section{Least Types}
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
do. For co-variant stacks, however, one can use the following idiom:
\begin{lstlisting}
@ -2677,14 +2677,14 @@ follows.
\begin{lstlisting}
def divmod(x: int, y: int) = Pair(x / y, x % y)
\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
using the names of the constructor parameters \lstinline@_$i$@, as in the following example:
\begin{lstlisting}
val xy = divmod(x, y);
System.out.println("quotient: " + x._1 + ", rest: " + x._2);
\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}
divmod(x, y) match {
case Pair(n, d) =>
@ -3153,7 +3153,7 @@ computation over lists, like:
\item extracting from a list all elements satisfying a criterion.
\item combine the elements of a list using some operator.
\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. We now discuss a set of commonly used higher-order
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)
}
\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}
def scaleList(xs: List[double], factor: double) =
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)
}
\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.
\begin{lstlisting}
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
divided without remainder only by one and itself. The most direct
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
\code{List.range} which is defined in object \code{List} as follows.
\begin{lstlisting}
@ -3270,7 +3270,7 @@ object List { ...
if (from >= end) Nil else from :: range(from + 1, end);
\end{lstlisting}
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.
\begin{lstlisting}
def isPrime(n: int) =
@ -3301,7 +3301,7 @@ def product(xs: List[int]): int = xs match {
case y :: ys => y * product(ys)
}
\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
inserts a given binary operator between adjacent elements of a given list.
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
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.
This notation builds a bridge between set-comprehensions in
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
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
column, row, or diagional). We will now develop a solution to this
problem, generalizing it to chessboards of arbitrary size. Hence, the
problem is to place $n$ queens on a chessboard of size $n \times n$.
column, row, or diagonal). We will now develop a solution to this
problem, generalizing it to chess-boards of arbitrary size. Hence, the
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.
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
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
@ -4006,7 +4006,7 @@ element for each solution.
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 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:
\begin{lstlisting}
def queens(n: int): List[List[int]] = {
@ -4041,7 +4041,7 @@ Here is a small example database:
\begin{lstlisting}
val books: List[Book] = List(
Book("Structure and Interpretation of Computer Programs",
List("Abelson, Harald", "Sussman, Gerald J.")),
List("Abelson, Harold", "Sussman, Gerald J.")),
Book("Principles of Compiler Design",
List("Aho, Alfred", "Ullman, Jeffrey")),
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
not needed but we would still like the flexibility of generators and
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}
for ( $s$ ) $e$
\end{lstlisting}
@ -4270,7 +4270,7 @@ theory underlying functional programming.
In this chapter, we introduce functions with side effects and study
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.
\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
{\em not} regarded as a variable definition, because the initializer
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
methods with a piece of state.}. If one does not know, or does not
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
case (first @ Pair(time, act)) :: ag1 =>
if (actiontime < time) Pair(actiontime, action) :: ag
else first :: insert(ag1)
else first :: insert(ag1)
}
agenda = insert(agenda)
}
@ -4801,7 +4801,7 @@ sum 15 new_value = false
\section{Summary}
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
computation. In particular, referential transparency is lost. On the
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
stateful objects. We have seen how real-world objects that change
with time can be modelled by changing the state of variables in a
computation. Time changes in the real world thus are modelled by time
with time can be modeled by changing the state of variables in a
computation. Time changes in the real world thus are modeled by time
changes in program execution. Of course, such time changes are usually
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
@ -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
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
done in computation. Instead of overwriting a variable with successive
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.
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)
rest \code{xs}. Instead of \code{xs ::: ys}, one uses the operation
\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 describe potentially infinite lists. However, there is no
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}
trait Iterator[+a] {
def hasNext: boolean;
@ -5035,7 +5035,7 @@ returns all elements of the original iterator that satisfy a criterion
\end{lstlisting}
In fact, \code{filter} returns instances of a subclass of iterators
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
\code{head}, but does not advance beyond that element. Hence, the
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]();
openJobs.write{
new Job {
type t = a;
def task = p;
def ret(x: a) = reply.set(x);
type t = a;
def task = p;
def ret(x: a) = reply.set(x);
}
}
() => reply.get
@ -6604,7 +6604,7 @@ As a simple example of how mailboxes are used, consider a
one-place buffer:
\begin{lstlisting}
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
m send Empty; // Initialization
def write(x: int): unit =
@ -6662,10 +6662,10 @@ Otherwise, the message is appended to the linked list of sent messages.
if (s1 != null) {
s.next = s1.next; s1.elem
} else {
val r = insert(lastReceiver, new Receiver {
val r = insert(lastReceiver, new Receiver {
def isDefined(msg: Any) = f.isDefinedAt(msg);
});
lastReceiver = r;
lastReceiver = r;
r.elem.wait();
r.elem.msg
}

View File

@ -44,7 +44,7 @@ varid ::= lower {letter $|$ digit} [`_' [id]]
id ::= upper {letter $|$ digit} [`_' [id]]
| varid
| op
| ```string chars`''
| ```string chars`''
\end{lstlisting}
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
with a special character followed by an arbitrary sequence of special
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
match rule applies. For instance, the string
@ -423,7 +423,7 @@ contravariant in their argument types.
\label{sec:synthetic-types}
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.
\subsection{Method Types}
@ -693,7 +693,7 @@ transitive relation that satisfies the following conditions.
one has $\mbox{\code{scala.AllRef}} \conforms T$.
\item A type variable or abstract type $t$ conforms to its upper bound and
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
$T$ conforms to $U$.
\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
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
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
which has a type specified as a least upper or greatest lower bound,
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
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@.
@ -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
$s_i$ and $s_j$ must be an import clause,
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{
Every basic definition may introduce several defined names, separated
@ -914,7 +914,7 @@ the type definition
\comment{
If an element in such a sequence introduces only the defined name,
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
more than just a defined name and parameters. Examples:
\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$@~
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
\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
is converted to a function type instead of being applied immediately,
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 following table:
\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 \\
B & B & B, 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
\end{tabular}\end{quote}
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.
@ -1773,9 +1773,9 @@ labeled \code{protected}.
If $M'$ is not an abstract member, then
$M$ must be labeled \code{override}.
\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
of $M$, then $M$ must also be labelled \code{abstract} and
of $M$, then $M$ must also be labeled \code{abstract} and
\code{override}.
\end{itemize}
@ -1852,11 +1852,11 @@ definition.
The \code{override} modifier has an additional significance when
combined with the \code{abstract} modifier. That modifier combination
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.
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
member of the template's superclass.
@ -2030,7 +2030,7 @@ This defines a class \code{LinkedList} with an overloaded constructor of type
\begin{lstlisting}
[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}
The second constructor alternative constructs an singleton list, while the
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 + (that: Double): Double; // double addition
def + (that: Float): Double; // float addtion
def + (that: Float): Double; // float addition
def + (that: Long): Long = // long addition
/* analogous for -, *, /, % */
@ -3935,7 +3935,7 @@ case class Tuple$n$[+a_1, ..., +a_n](_1: a_1, ..., _$n$: a_$n$) {
}
\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}
as an alias for \code{Tuple3}.
@ -3979,7 +3979,7 @@ class PartialFunction[-a,+b] extends Function1[a, b] {
}
\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}.
\subsection{Class \large{\code{Array}}}\label{cls:array}
@ -4019,7 +4019,7 @@ module Array {
\section{The \large{\code{Predef}} Object}\label{cls:predef}
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
definition for the JVM environment.
@ -4076,504 +4076,3 @@ object Predef {
}
\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
}

View File

@ -22,7 +22,5 @@ Martin Odersky
\input{RationalePart}
\bibliographystyle{alpha}
\bibliography{Scala}
\end{document}

View File

@ -93,9 +93,12 @@ Matthias Zenger \\[25mm]\ }
\input{RationalePart}
\part{The Scala Language Specification}
\input{ReferencePart}
\bibliographystyle{alpha}
\bibliography{Scala}
\input{ReferencePartAppendix}
\end{document}

View File

@ -96,6 +96,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
}
def lateEnter(unit: Unit, sym: Symbol): unit = {
//System.out.println("late enter: " + sym + " " + sym.isModule());//DEBUG
enterUnit(unit);
if (sym.rawFirstInfo().isInstanceOf[SourceCompleter]) {
sym.setInfo(Type.ErrorType);

View File

@ -2,14 +2,14 @@ bug95.scala:1: illegal inheritance from sealed class
class C extends AnyVal;
^
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;
^
bug95.scala:2: illegal inheritance from sealed class
class T extends Unit;
^
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;
^
four errors found