diff options
-rw-r--r-- | 05-types.md | 36 | ||||
-rw-r--r-- | 07-classes-and-objects.md | 101 | ||||
-rw-r--r-- | 09-implicit-parameters-and-views.md | 30 | ||||
-rw-r--r-- | 14-the-scala-standard-library.md | 3 |
4 files changed, 77 insertions, 93 deletions
diff --git a/05-types.md b/05-types.md index 294b87a71d..876d8eea15 100644 --- a/05-types.md +++ b/05-types.md @@ -933,10 +933,10 @@ i.e.\ it is transitive and reflexive. _least upper bounds_ and _greatest lower bounds_ of a set of types are understood to be relative to that order. - -> **Note**: The least upper bound or greatest lower bound -> of a set of types does not always exist. For instance, consider -> the class definitions +###### Note +The least upper bound or greatest lower bound +of a set of types does not always exist. For instance, consider +the class definitions ``` class A[+T] {} @@ -944,20 +944,20 @@ class B extends A[B] class C extends A[C] ``` -> Then the types `A[Any], A[A[Any]], A[A[A[Any]]], ...` form -> a descending sequence of upper bounds for `B` and `C`. The -> least upper bound would be the infinite limit of that sequence, which -> 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 -> limit [^4]. -> -> The least upper bound or greatest lower bound might also not be -> unique. For instance `A with B` and `B with A` are both -> greatest lower of `A` and `B`. If there are several -> least upper bounds or greatest lower bounds, the Scala compiler is -> free to pick any one of them. +Then the types `A[Any], A[A[Any]], A[A[A[Any]]], ...` form +a descending sequence of upper bounds for `B` and `C`. The +least upper bound would be the infinite limit of that sequence, which +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 +limit [^4]. + +The least upper bound or greatest lower bound might also not be +unique. For instance `A with B` and `B with A` are both +greatest lower of `A` and `B`. If there are several +least upper bounds or greatest lower bounds, the Scala compiler is +free to pick any one of them. [^4]: The current Scala compiler limits the nesting level diff --git a/07-classes-and-objects.md b/07-classes-and-objects.md index 392da29d0f..46581df80b 100644 --- a/07-classes-and-objects.md +++ b/07-classes-and-objects.md @@ -185,23 +185,24 @@ on base classes forms in general a directed acyclic graph. A linearization of this graph is defined as follows. -> Let $C$ be a class with template -> `$C_1$ with ... with $C_n$ { $\mathit{stats}$ }`. -> The _linearization_ of $C$, $\mathcal{L}(C)$ is defined as follows: -> -> $\mathcal{L}(C) = C, \mathcal{L}(C_n) \; \vec{+} \; \ldots \; \vec{+} \; \mathcal{L}(C_1)$ -> -> Here $\vec{+}$ denotes concatenation where elements of the right operand -> replace identical elements of the left operand: -> -> ``` -> \[ -> \begin{array}{lcll} -> \{a, A\} \;\vec{+}\; B &=& a, (A \;\vec{+}\; B) &{\bf if} \; a \not\in B \\ -> &=& A \;\vec{+}\; B &{\bf if} \; a \in B -> \end{array} -> \] -> ``` +###### Definition: linearization +Let $C$ be a class with template +`$C_1$ with ... with $C_n$ { $\mathit{stats}$ }`. +The _linearization_ of $C$, $\mathcal{L}(C)$ is defined as follows: + +$\mathcal{L}(C) = C, \mathcal{L}(C_n) \; \vec{+} \; \ldots \; \vec{+} \; \mathcal{L}(C_1)$ + +Here $\vec{+}$ denotes concatenation where elements of the right operand +replace identical elements of the left operand: + +``` +\[ +\begin{array}{lcll} +\{a, A\} \;\vec{+}\; B &=& a, (A \;\vec{+}\; B) &{\bf if} \; a \not\in B \\ + &=& A \;\vec{+}\; B &{\bf if} \; a \in B +\end{array} +\] +``` ###### Example @@ -223,10 +224,10 @@ Then the linearization of class `Iter` is Note that the linearization of a class refines the inheritance relation: if $C$ is a subclass of $D$, then $C$ precedes $D$ in any linearization where both $C$ and $D$ occur. -\ref{def:lin} also satisfies the property that a linearization -of a class always contains the linearization of its direct superclass -as a suffix. For instance, the linearization of -`StringIterator` is +[Linearization](#definition-linearization) also satisfies the property that +a linearization of a class always contains the linearization of its direct superclass as a suffix. + +For instance, the linearization of `StringIterator` is ``` { StringIterator, AbsIterator, AnyRef, Any } @@ -245,9 +246,7 @@ which is not a suffix of the linearization of `Iter`. ### Class Members - -A class $C$ defined by a template -`$C_1$ with $\ldots$ with $C_n$ { $\mathit{stats}$ }` +A class $C$ defined by a template `$C_1$ with $\ldots$ with $C_n$ { $\mathit{stats}$ }` can define members in its statement sequence $\mathit{stats}$ and can inherit members from all parent classes. Scala adopts Java and C\#'s conventions for static overloading of @@ -257,19 +256,18 @@ member of a class $C$ overrides a member of a parent class, or whether the two co-exist as overloaded variants in $C$, Scala uses the following definition of _matching_ on members: -> **Definition** -> A member definition $M$ _matches_ a member definition $M'$, if $M$ -> and $M'$ bind the same name, and one of following holds. -> -> 1. Neither $M$ nor $M'$ is a method definition. -> 2. $M$ and $M'$ define both monomorphic methods with equivalent argument -> types. -> 3. $M$ defines a parameterless method and $M'$ defines a method -> with an empty parameter list `()` or _vice versa_. -> 4. $M$ and $M'$ define both polymorphic methods with -> equal number of argument types $\overline T$, $\overline T'$ -> and equal numbers of type parameters -> $\overline t$, $\overline t'$, say, and $\overline T' = [\overline t'/\overline t]\overline T$. +###### Definition: matching +A member definition $M$ _matches_ a member definition $M'$, if $M$ +and $M'$ bind the same name, and one of following holds. + +1. Neither $M$ nor $M'$ is a method definition. +2. $M$ and $M'$ define both monomorphic methods with equivalent argument types. +3. $M$ defines a parameterless method and $M'$ defines a method + with an empty parameter list `()` or _vice versa_. +4. $M$ and $M'$ define both polymorphic methods with + equal number of argument types $\overline T$, $\overline T'$ + and equal numbers of type parameters + $\overline t$, $\overline t'$, say, and $\overline T' = [\overline t'/\overline t]\overline T$. <!-- every argument type @@ -282,23 +280,22 @@ Members of class $C$ are either _directly defined_ (i.e.\ they appear in $C$'s statement sequence $\mathit{stats}$) or they are _inherited_. There are two rules that determine the set of members of a class, one for each category: -> A _concrete member_ of a class $C$ is any concrete definition $M$ in -> some class $C_i \in \mathcal{L}(C)$, except if there is a preceding class -> $C_j \in \mathcal{L}(C)$ where $j < i$ which directly defines a concrete -> member $M'$ matching $M$. -> -> An _abstract member_ of a class $C$ is any abstract definition $M$ -> in some class $C_i \in \mathcal{L}(C)$, except if $C$ contains already a -> concrete member $M'$ matching $M$, or if there is a preceding class -> $C_j \in \mathcal{L}(C)$ where $j < i$ which directly defines an abstract -> member $M'$ matching $M$. +A _concrete member_ of a class $C$ is any concrete definition $M$ in +some class $C_i \in \mathcal{L}(C)$, except if there is a preceding class +$C_j \in \mathcal{L}(C)$ where $j < i$ which directly defines a concrete +member $M'$ matching $M$. + +An _abstract member_ of a class $C$ is any abstract definition $M$ +in some class $C_i \in \mathcal{L}(C)$, except if $C$ contains already a +concrete member $M'$ matching $M$, or if there is a preceding class +$C_j \in \mathcal{L}(C)$ where $j < i$ which directly defines an abstract +member $M'$ matching $M$. This definition also determines the [overriding](#overriding) relationships between matching members of a class $C$ and its parents. First, a concrete definition always overrides an abstract definition. -Second, for -definitions $M$ and $M$' which are both concrete or both abstract, $M$ -overrides $M'$ if $M$ appears in a class that precedes (in the +Second, for definitions $M$ and $M$' which are both concrete or both abstract, +$M$ overrides $M'$ if $M$ appears in a class that precedes (in the linearization of $C$) the class in which $M'$ is defined. It is an error if a template directly defines two matching members. It @@ -663,7 +660,7 @@ new m.C(0) {} // **** error: illegal inheritance from sealed class. ``` A similar access restriction can be achieved by marking the primary -constructor `private` (see \ref{ex:private-constr}). +constructor `private` ((example)[#example-private-constructor]). ## Class Definitions @@ -749,7 +746,7 @@ which when applied to parameters conforming to types $\mathit{ps}$ initializes instances of type `$c$[$\mathit{tps}\,$]` by evaluating the template $t$. -###### Example +###### Example: private constructor The following example illustrates `val` and `var` parameters of a class `C`: ``` diff --git a/09-implicit-parameters-and-views.md b/09-implicit-parameters-and-views.md index e4b8b5956c..a88ebbc069 100644 --- a/09-implicit-parameters-and-views.md +++ b/09-implicit-parameters-and-views.md @@ -188,28 +188,19 @@ common element and $T$ is more complex than $U$. The set of _top-level type constructors_ $\mathit{ttcs}(T)$ of a type $T$ depends on the form of the type: -> For a type designator, \ -> $\mathit{ttcs}(p.c) ~=~ \{c\}$; \ -> For a parameterized type, \ -> $\mathit{ttcs}(p.c[\mathit{targs}]) ~=~ \{c\}$; \ -> For a singleton type, \ -> $\mathit{ttcs}(p.type) ~=~ \mathit{ttcs}(T)$, provided $p$ has type $T$;\ -> For a compound type, \ -> `$\mathit{ttcs}(T_1$ with $\ldots$ with $T_n)$` $~=~ \mathit{ttcs}(T_1) \cup \ldots \cup \mathit{ttcs}(T_n)$. +- For a type designator, $\mathit{ttcs}(p.c) ~=~ \{c\}$; +- For a parameterized type, $\mathit{ttcs}(p.c[\mathit{targs}]) ~=~ \{c\}$; +- For a singleton type, $\mathit{ttcs}(p.type) ~=~ \mathit{ttcs}(T)$, provided $p$ has type $T$; +- For a compound type, `$\mathit{ttcs}(T_1$ with $\ldots$ with $T_n)$` $~=~ \mathit{ttcs}(T_1) \cup \ldots \cup \mathit{ttcs}(T_n)$. The _complexity_ $\mathit{complexity}(T)$ of a core type is an integer which also depends on the form of the type: -> For a type designator, \ -> $\mathit{complexity}(p.c) ~=~ 1 + \mathit{complexity}(p)$ \ -> For a parameterized type, \ -> $\mathit{complexity}(p.c[\mathit{targs}]) ~=~ 1 + \Sigma \mathit{complexity}(\mathit{targs})$ \ -> For a singleton type denoting a package $p$, \ -> $\mathit{complexity}(p.type) ~=~ 0$ \ -> For any other singleton type, \ -> $\mathit{complexity}(p.type) ~=~ 1 + \mathit{complexity}(T)$, provided $p$ has type $T$; \ -> For a compound type, \ -> `$\mathit{complexity}(T_1$ with $\ldots$ with $T_n)$` $= \Sigma\mathit{complexity}(T_i)$ +- For a type designator, $\mathit{complexity}(p.c) ~=~ 1 + \mathit{complexity}(p)$ +- For a parameterized type, $\mathit{complexity}(p.c[\mathit{targs}]) ~=~ 1 + \Sigma \mathit{complexity}(\mathit{targs})$ +- For a singleton type denoting a package $p$, $\mathit{complexity}(p.type) ~=~ 0$ +- For any other singleton type, $\mathit{complexity}(p.type) ~=~ 1 + \mathit{complexity}(T)$, provided $p$ has type $T$; +- For a compound type, `$\mathit{complexity}(T_1$ with $\ldots$ with $T_n)$` $= \Sigma\mathit{complexity}(T_i)$ ###### Example @@ -257,8 +248,7 @@ defined by an implicit value which has function type `$S$=>$T$` or `(=>$S$)=>$T$` or by a method convertible to a value of that type. -Views are applied in three situations. - +Views are applied in three situations: 1. If an expression $e$ is of type $T$, and $T$ does not conform to the expression's expected type $\mathit{pt}$. In this case an implicit $v$ is diff --git a/14-the-scala-standard-library.md b/14-the-scala-standard-library.md index 3bfeb9013c..37174b8af3 100644 --- a/14-the-scala-standard-library.md +++ b/14-the-scala-standard-library.md @@ -6,11 +6,8 @@ the following. ![Class hierarchy of Scala](resources/classhierarchy.pdf) - ## Root Classes -Figure~\ref{fig:class-hierarchy} illustrates Scala's class -hierarchy. The root of this hierarchy is formed by class `Any`. Every class in a Scala execution environment inherits directly or indirectly from this class. Class `Any` has two direct |