From d8888a99cf2675e698744d1f21f90cdee42609b1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 8 Jan 2004 15:52:45 +0000 Subject: *** empty log message *** --- doc/reference/ScalaByExample.tex | 64 ++++++++++++++++++++------------------- doc/reference/ScalaReference.tex | 65 ++++++++++++---------------------------- 2 files changed, 53 insertions(+), 76 deletions(-) (limited to 'doc') diff --git a/doc/reference/ScalaByExample.tex b/doc/reference/ScalaByExample.tex index b0aed6d462..cb75ba7ddd 100644 --- a/doc/reference/ScalaByExample.tex +++ b/doc/reference/ScalaByExample.tex @@ -6210,23 +6210,23 @@ A synchronized variable (or syncvar for short) offers \code{get} and block until the variable has been defined. An \code{unset} operation resets the variable to undefined state. -Synchronized variables can be implemented as follows. +Here's the standard implementation of synchronized variables. \begin{lstlisting} -class SyncVar[a] extends Monitor { - private val defined = new Signal; - private var isDefined: boolean = false; - private var value: a; +package scala.concurrent; +class SyncVar[a] with Monitor { + private var isDefined: Boolean = false; + private var value: a = _; def get = synchronized { - if (!isDefined) defined.wait; + if (!isDefined) wait(); value } def set(x: a) = synchronized { - value = x ; isDefined = true ; defined.send; + value = x ; isDefined = true ; notifyAll(); } - def isSet: boolean = + def isSet: Boolean = isDefined; - def unset = synchronized { - isDefined = false; + def unset = synchronized { + isDefined = false; } } \end{lstlisting} @@ -6240,18 +6240,20 @@ Futures are used in order to make good use of parallel processing resources. A typical usage is: \begin{lstlisting} +import scala.concurrent.ops._; +... val x = future(someLengthyComputation); anotherLengthyComputation; val y = f(x()) + g(x()); \end{lstlisting} -Futures can be implemented in Scala as follows. - +The \code{future} method is defined in object +\code{scala.concurrent.ops} as follows. \begin{lstlisting} def future[a](def p: a): unit => a = { val result = new SyncVar[a]; fork { result.set(p) } - (=> result.get) + (() => result.get) } \end{lstlisting} @@ -6275,31 +6277,33 @@ The next example presents a function \code{par} which takes a pair of computations as parameters and which returns the results of the computations in another pair. The two computations are performed in parallel. +The function is defined in object +\code{scala.concurrent.ops} as follows. \begin{lstlisting} -def par[a, b](def xp: a, def yp: b): (a, b) = { - val y = new SyncVar[a]; - fork { y.set(yp) } - (xp, y) -} + def par[a, b](def xp: a, def yp: b): Pair[a, b] = { + val y = new SyncVar[b]; + spawn { y set yp } + Pair(xp, y.get) + } \end{lstlisting} - -The next example presents a function \code{replicate} which performs a +Defined in the same place is a function \code{replicate} which performs a number of replicates of a computation in parallel. Each replication instance is passed an integer number which identifies it. - \begin{lstlisting} -def replicate(start: int, end: int)(def p: int => unit): unit = { - if (start == end) { - } else if (start + 1 == end) { - p(start) - } else { - val mid = (start + end) / 2; - par ( replicate(start, mid)(p), replicate(mid, end)(p) ) + def replicate(start: Int, end: Int)(p: Int => Unit): Unit = { + if (start == end) + () + else if (start + 1 == end) + p(start) + else { + val mid = (start + end) / 2; + spawn { replicate(start, mid)(p) } + replicate(mid, end)(p) + } } -} \end{lstlisting} -The next example shows how to use \code{replicate} to perform parallel +The next function uses \code{replicate} to perform parallel computations on all elements of an array. \begin{lstlisting} diff --git a/doc/reference/ScalaReference.tex b/doc/reference/ScalaReference.tex index fa5a795b65..c62e0f04b4 100644 --- a/doc/reference/ScalaReference.tex +++ b/doc/reference/ScalaReference.tex @@ -304,7 +304,7 @@ referenced entity in $T$. Type ::= Type1 `=>' Type | `(' [Types] `)' `=>' Type | Type1 - Type1 ::= SimpleType {with SimpleType} [Refinement] + Type1 ::= SimpleType {with SimpleType} SimpleType ::= StableId | SimpleType `#' id | Path `.' type @@ -318,14 +318,12 @@ take type parameters and yield types. A subset of first-order types called {\em value types} represents sets of (first-class) values. Value types are either {\em concrete} or {\em abstract}. Every concrete value type can be represented as a {\em class type}, i.e.\ a -type designator (\sref{sec:type-desig}) that refers to a -class\footnote{We assume that objects and packages also -implicitly define a class (of the same name as the object or package, -but inaccessible to user programs).} (\sref{sec:classes}), -or as a {\em compound type} (\sref{sec:compound-types}) -consisting of class types and possibly -also a refinement (\sref{sec:refinements}) that further constrains the -types of its members. +type designator (\sref{sec:type-desig}) that refers to a +class\footnote{We assume that objects and packages also implicitly +define a class (of the same name as the object or package, but +inaccessible to user programs).} (\sref{sec:classes}), or as a {\em +compound type} (\sref{sec:compound-types}) of class types. +\todo{verify whether operands need to be class types} A shorthand exists for denoting function types (\sref{sec:function-types}). Abstract value types are introduced by @@ -474,25 +472,14 @@ the following types are ill-formed: \label{sec:compound-types} \syntax\begin{lstlisting} - Type ::= SimpleType {with SimpleType} [Refinement] - Refinement ::= `{' [RefineStat {`;' RefineStat}] `}' - RefineStat ::= Dcl - | type TypeDef {`,' TypeDef} - | + Type ::= SimpleType {with SimpleType} \end{lstlisting} -A compound type ~\lstinline@$T_1$ with $\ldots$ with $T_n$ {$R\,$}@~ represents -objects with members as given in the component types $T_1 \commadots -T_n$ and the refinement \lstinline@{$R\,$}@. Each component type $T_i$ must be a -class type and the base class sequence generated by types $T_1 -\commadots T_n$ must be well-formed (\sref{sec:basetypes-wf}). A -refinement \lstinline@{$R\,$}@ contains declarations and type -definitions. Each declaration or definition in a refinement must -override a declaration or definition in one of the component types -$T_1 \commadots T_n$. The usual rules for overriding (\sref{}) -apply. If no refinement is given, the empty refinement is implicitly -added, i.e. ~\lstinline@$T_1$ with $\ldots$ with $T_n$@~ is a shorthand for -~\lstinline@$T_1$ with $\ldots$ with $T_n$ {}@. +A compound type ~\lstinline@$T_1$ with $\ldots$ with $T_n$ {$R\,$}@~ +represents objects with members as given in the component types $T_1 +\commadots T_n$. Each component type $T_i$ must be a class type and +the base class sequence generated by types $T_1 \commadots T_n$ must +be well-formed (\sref{sec:basetypes-wf}). \subsection{Function Types} \label{sec:function-types} @@ -758,10 +745,7 @@ consisting only of package or object selectors and ending in $O$, then ~\lstinline@$O$.this.type $\equiv p$.type@. \item Two compound types are equivalent if their component types are -pairwise equivalent and their refinements are equivalent. Two -refinements are equivalent if they bind the same names and the -modifiers, types and bounds of every declared entity are equivalent in -both refinements. +pairwise equivalent. \item Two method types are equivalent if they have equivalent result types, both have the same number of parameters, and corresponding @@ -938,9 +922,8 @@ the expression is typed and evaluated is if it was \end{lstlisting} A {\em declaration} introduces names and assigns them types. It can -appear as one of the statements of a class definition -(\sref{sec:templates}) or as part of a refinement in a compound -type (\sref{sec:refinements}). +only appear as one of the statements of a class definition +(\sref{sec:templates}). A {\em definition} introduces names that denote terms or types. It can form part of an object or class definition or it can be local to a @@ -2720,13 +2703,7 @@ constructor invocations (of types $S, T_1 \commadots T_n$, say) and $stats$ is a statement sequence containing initializer statements and member definitions (\sref{sec:members}). The type of such an instance creation expression is then the compound type -\lstinline@$S$ with $T_1$ with $\ldots$ with $T_n$ {$R\,$}@, -where \lstinline@{$R\,$}@ is -a refinement (\sref{sec:compound-types}) which declares exactly those -members of $stats$ that override a member of $S$ or $T_1 \commadots -T_n$. \todo{what about methods and overloaded defs?} For this type to -be well-formed, $R$ may not reference types defined in $stats$ which -do not themselves form part of $R$. +\lstinline@$S$ with $T_1$ with $\ldots$ with $T_n$@. The instance creation expression is evaluated by creating a fresh object, which is initialized by evaluating the expression template. @@ -3398,7 +3375,7 @@ Concretely, we distinguish the following kinds of patterns. A {\em wild-card pattern} \_ matches any value. A {\em typed pattern} $\_: T$ matches values of type $T$. The type $T$ may be - a class type or a compound type; it may not contain a refinement (\sref{sec:refinements}). + a class type or a compound type. This pattern matches any non-null value of type $T$. $T$ must conform to the pattern's expected type. A pattern $x:T$ is treated the same way as $x @ (_:T)$ @@ -4260,7 +4237,7 @@ grammar. Type ::= Type1 `=>' Type | `(' [Types] `)' `=>' Type | Type1 - Type1 ::= SimpleType {with SimpleType} [Refinement] + Type1 ::= SimpleType {with SimpleType} SimpleType ::= SimpleType TypeArgs | SimpleType `#' id | StableId @@ -4268,10 +4245,6 @@ grammar. | `(' Type ')' TypeArgs ::= `[' Types `]' Types ::= Type {`,' Type} - Refinement ::= `{' [RefineStat {`;' RefineStat}] `}' - RefineStat ::= Dcl - | type TypeDef {`,' TypeDef} - | Exprs ::= Expr {`,' Expr} Expr ::= Bindings `=>' Expr -- cgit v1.2.3