diff options
-rw-r--r-- | 03-lexical-syntax.md | 237 | ||||
-rw-r--r-- | 04-identifiers-names-and-scopes.md | 78 | ||||
-rw-r--r-- | 05-types.md | 324 | ||||
-rw-r--r-- | 06-basic-declarations-and-definitions.md | 526 | ||||
-rw-r--r-- | 07-classes-and-objects.md | 570 | ||||
-rw-r--r-- | 08-expressions.md | 571 | ||||
-rw-r--r-- | 09-implicit-parameters-and-views.md | 182 | ||||
-rw-r--r-- | 10-pattern-matching.md | 342 | ||||
-rw-r--r-- | 11-top-level-definitions.md | 84 | ||||
-rw-r--r-- | 12-xml-expressions-and-patterns.md | 5 | ||||
-rw-r--r-- | 14-the-scala-standard-library.md | 114 |
11 files changed, 1561 insertions, 1472 deletions
diff --git a/03-lexical-syntax.md b/03-lexical-syntax.md index 30b4ffdade..ea82d257f0 100644 --- a/03-lexical-syntax.md +++ b/03-lexical-syntax.md @@ -95,19 +95,19 @@ _ : = => <- <: <% >: # @ The Unicode operators \\u21D2 ‘$\Rightarrow$’ and \\u2190 ‘$\leftarrow$’, which have the ASCII equivalents ‘=>’ and ‘<-’, are also reserved. -(@) Here are examples of identifiers: +###### Example: here are some identifiers: - ``` - x Object maxIndex p2p empty_? - + `yield` αρετη _y dot_product_* - __system _MAX_LEN_ - ``` +``` + x Object maxIndex p2p empty_? + + `yield` αρετη _y dot_product_* + __system _MAX_LEN_ +``` -(@) Backquote-enclosed strings are a solution when one needs to - access Java identifiers that are reserved words in Scala. For - instance, the statement `Thread.yield()` is illegal, since - `yield` is a reserved word in Scala. However, here's a - work-around: `` Thread.`yield`() `` +###### Example: backquote-enclosed strings +When one needs to access Java identifiers that are reserved words in Scala, use backquote-enclosed strings. +For instance, the statement `Thread.yield()` is illegal, since +`yield` is a reserved word in Scala. However, here's a +work-around: `` Thread.`yield`() `` ## Newline Characters @@ -202,96 +202,97 @@ A single new line token is accepted - in front of a [parameter clause](#function-declarations-and-definitions), and - after an [annotation](#user-defined-annotations). -(@) The following code contains four well-formed statements, each - on two lines. The newline tokens between the two lines are not - treated as statement separators. +###### Example: four well-formed statements, each on two lines - ``` - if (x > 0) - x = x - 1 +The newline tokens between the two lines are not +treated as statement separators. - while (x > 0) - x = x / 2 +``` +if (x > 0) + x = x - 1 - for (x <- 1 to 10) - println(x) +while (x > 0) + x = x / 2 - type - IntList = List[Int] - ``` +for (x <- 1 to 10) + println(x) -(@) The following code designates an anonymous class: +type + IntList = List[Int] +``` - ``` - new Iterator[Int] - { - private var x = 0 - def hasNext = true - def next = { x += 1; x } - } - ``` +###### Example: an anonymous class - With an additional newline character, the same code is interpreted as - an object creation followed by a local block: +``` +new Iterator[Int] +{ + private var x = 0 + def hasNext = true + def next = { x += 1; x } +} +``` - ``` - new Iterator[Int] +With an additional newline character, the same code is interpreted as +an object creation followed by a local block: - { - private var x = 0 - def hasNext = true - def next = { x += 1; x } - } - ``` +``` +new Iterator[Int] -(@) The following code designates a single expression: +{ + private var x = 0 + def hasNext = true + def next = { x += 1; x } +} +``` - ``` - x < 0 || - x > 10 - ``` +###### Example: a single expression - With an additional newline character, the same code is interpreted as - two expressions: +``` + x < 0 || + x > 10 +``` - ``` - x < 0 || +With an additional newline character, the same code is interpreted as +two expressions: - x > 10 - ``` +``` + x < 0 || -(@) The following code designates a single, curried function definition: + x > 10 +``` - ``` - def func(x: Int) - (y: Int) = x + y - ``` +###### Example: a single, curried function definition - With an additional newline character, the same code is interpreted as - an abstract function definition and a syntactically illegal statement: +``` +def func(x: Int) + (y: Int) = x + y +``` + +With an additional newline character, the same code is interpreted as +an abstract function definition and a syntactically illegal statement: - ``` - def func(x: Int) +``` +def func(x: Int) - (y: Int) = x + y - ``` + (y: Int) = x + y +``` -(@) The following code designates an attributed definition: +###### Example: an attributed definition - ``` - @serializable - protected class Data { ... } - ``` +``` +@serializable +protected class Data { ... } +``` - With an additional newline character, the same code is interpreted as - an attribute and a separate statement (which is syntactically - illegal). +With an additional newline character, the same code is interpreted as +an attribute and a separate statement (which is syntactically +illegal). - ``` - @serializable +``` +@serializable - protected class Data { ... } - ``` +protected class Data { ... } +``` ## Literals @@ -349,7 +350,7 @@ is _pt_. The numeric ranges given by these types are: `Char` $0$ to $2^{16}-1$ --------------- ----------------------- -(@) Here are some integer literals: +###### Example: some integer literals ``` 0 21 0xFFFFFFFF -42L @@ -378,17 +379,20 @@ If a floating point literal in a program is followed by a token starting with a letter, there must be at least one intervening whitespace character between the two tokens. -(@) Here are some floating point literals: +###### Example: some floating point literals + +``` +0.0 1e30f 3.14159f 1.0e-100 .1 +``` + +###### Example: tokenizing - ``` - 0.0 1e30f 3.14159f 1.0e-100 .1 - ``` +The phrase `1.toString` parses as three different tokens: +the integer literal `1`, a `.`, and the identifier `toString`. -(@) The phrase `1.toString` parses as three different tokens: - the integer literal `1`, a `.`, and the identifier `toString`. +###### Example: invalid floating point literal -(@) `1.` is not a valid floating point literal, because the - mandatory digit after the `.` is missing. +`1.` is not a valid floating point literal because the mandatory digit after the `.` is missing. ### Boolean Literals @@ -411,11 +415,11 @@ A character literal is a single character enclosed in quotes. The character is either a printable unicode character or is described by an [escape sequence](#escape-sequences). -(@) Here are some character literals: +###### Example: some character literals - ``` - 'a' '\u0041' '\n' '\t' - ``` +``` +'a' '\u0041' '\n' '\t' +``` Note that `'\u000A'` is _not_ a valid character literal because Unicode conversion is done before literal parsing and the Unicode @@ -438,12 +442,12 @@ contains a double quote character, it must be escaped, i.e. `"\""`. The value of a string literal is an instance of class `String`. -(@) Here are some string literals: +###### Example: some string literals - ``` - "Hello,\nWorld!" - "This string contains a \" character." - ``` +``` +"Hello,\nWorld!" +"This string contains a \" character." +``` #### Multi-Line String Literals @@ -460,21 +464,21 @@ must not necessarily be printable; newlines or other control characters are also permitted. Unicode escapes work as everywhere else, but none of the escape sequences [here](#escape-sequences) are interpreted. -(@) Here is a multi-line string literal: +###### Example: a multi-line string literal: - ``` - """the present string - spans three - lines.""" - ``` +``` + """the present string + spans three + lines.""" +``` - This would produce the string: +This would produce the string: - ``` - the present string - spans three - lines. - ``` +``` +the present string + spans three + lines. +``` The Scala library contains a utility method `stripMargin` which can be used to strip leading whitespace from multi-line strings. @@ -591,14 +595,15 @@ The scanner switches from XML mode to Scala mode if either Note that no Scala tokens are constructed in XML mode, and that comments are interpreted as text. -(@) The following value definition uses an XML literal with two embedded -Scala expressions +###### Example: XML literals - ``` - val b = <book> - <title>The Scala Language Specification</title> - <version>{scalaBook.version}</version> - <authors>{scalaBook.authors.mkList("", ", ", "")}</authors> - </book> - ``` +The following value definition uses an XML literal with two embedded +Scala expressions: +``` +val b = <book> + <title>The Scala Language Specification</title> + <version>{scalaBook.version}</version> + <authors>{scalaBook.authors.mkList("", ", ", "")}</authors> + </book> +``` diff --git a/04-identifiers-names-and-scopes.md b/04-identifiers-names-and-scopes.md index 1e74e52b5f..7caedb0241 100644 --- a/04-identifiers-names-and-scopes.md +++ b/04-identifiers-names-and-scopes.md @@ -54,44 +54,46 @@ is bound by a definition or declaration, then $x$ refers to the entity introduced by that binding. In that case, the type of $x$ is the type of the referenced entity. -(@) Assume the following two definitions of a objects named `X` in packages `P` and `Q`. - - ``` - package P { - object X { val x = 1; val y = 2 } - } - - package Q { - object X { val x = true; val y = "" } - } - ``` - - The following program illustrates different kinds of bindings and - precedences between them. - - ``` - package P { // `X' bound by package clause - import Console._ // `println' bound by wildcard import - object A { - println("L4: "+X) // `X' refers to `P.X' here - object B { - import Q._ // `X' bound by wildcard import - println("L7: "+X) // `X' refers to `Q.X' here - import X._ // `x' and `y' bound by wildcard import - println("L8: "+x) // `x' refers to `Q.X.x' here - object C { - val x = 3 // `x' bound by local definition - println("L12: "+x) // `x' refers to constant `3' here - { import Q.X._ // `x' and `y' bound by wildcard import - // println("L14: "+x) // reference to `x' is ambiguous here - import X.y // `y' bound by explicit import - println("L16: "+y) // `y' refers to `Q.X.y' here - { val x = "abc" // `x' bound by local definition - import P.X._ // `x' and `y' bound by wildcard import - // println("L19: "+y) // reference to `y' is ambiguous here - println("L20: "+x) // `x' refers to string ``abc'' here - }}}}}} - ``` +###### Example: bindings + +Assume the following two definitions of a objects named `X` in packages `P` and `Q`. + +``` +package P { + object X { val x = 1; val y = 2 } +} + +package Q { + object X { val x = true; val y = "" } +} +``` + +The following program illustrates different kinds of bindings and +precedences between them. + +``` +package P { // `X' bound by package clause +import Console._ // `println' bound by wildcard import +object A { + println("L4: "+X) // `X' refers to `P.X' here + object B { + import Q._ // `X' bound by wildcard import + println("L7: "+X) // `X' refers to `Q.X' here + import X._ // `x' and `y' bound by wildcard import + println("L8: "+x) // `x' refers to `Q.X.x' here + object C { + val x = 3 // `x' bound by local definition + println("L12: "+x) // `x' refers to constant `3' here + { import Q.X._ // `x' and `y' bound by wildcard import +// println("L14: "+x) // reference to `x' is ambiguous here + import X.y // `y' bound by explicit import + println("L16: "+y) // `y' refers to `Q.X.y' here + { val x = "abc" // `x' bound by local definition + import P.X._ // `x' and `y' bound by wildcard import +// println("L19: "+y) // reference to `y' is ambiguous here + println("L20: "+x) // `x' refers to string ``abc'' here +}}}}}} +``` A reference to a qualified (type- or term-) identifier $e.x$ refers to the member of the type $T$ of $e$ which has the name $x$ in the same diff --git a/05-types.md b/05-types.md index 25210294ea..294b87a71d 100644 --- a/05-types.md +++ b/05-types.md @@ -143,16 +143,18 @@ A qualified type designator has the form `p.t` where `p` is a [path](#paths) and _t_ is a type name. Such a type designator is equivalent to the type projection `p.type#t`. -(@) Some type designators and their expansions are listed below. We assume - a local type parameter $t$, a value `maintable` - with a type member `Node` and the standard class `scala.Int`, +###### Example: fully qualified type designators - -------------------- -------------------------- - t ε.type#t - Int scala.type#Int - scala.Int scala.type#Int - data.maintable.Node data.maintable.type#Node - -------------------- -------------------------- +Some type designators and their expansions are listed below. We assume +a local type parameter $t$, a value `maintable` +with a type member `Node` and the standard class `scala.Int`, + +|-------------------- | --------------------------| +|t | ε.type#t | +|Int | scala.type#Int | +|scala.Int | scala.type#Int | +|data.maintable.Node | data.maintable.type#Node | +|-------------------- | --------------------------| ### Parameterized Types @@ -173,44 +175,47 @@ well-formed if each actual type parameter _conforms to its bounds_, i.e. $\sigma L_i <: T_i <: \sigma U_i$ where $\sigma$ is the substitution $[ a_1 := T_1 , \ldots , a_n := T_n ]$. -(@param-types) Given the partial type definitions: +###### Example: parameterized types +Given the partial type definitions: - ``` - class TreeMap[A <: Comparable[A], B] { … } - class List[A] { … } - class I extends Comparable[I] { … } - - class F[M[_], X] { … } - class S[K <: String] { … } - class G[M[ Z <: I ], I] { … } - ``` +``` +class TreeMap[A <: Comparable[A], B] { … } +class List[A] { … } +class I extends Comparable[I] { … } - the following parameterized types are well formed: +class F[M[_], X] { … } +class S[K <: String] { … } +class G[M[ Z <: I ], I] { … } +``` - ``` - TreeMap[I, String] - List[I] - List[List[Boolean]] - - F[List, Int] - G[S, String] - ``` +the following parameterized types are well formed: -(@) Given the type definitions of (@param-types), - the following types are ill-formed: +``` +TreeMap[I, String] +List[I] +List[List[Boolean]] - ``` - TreeMap[I] // illegal: wrong number of parameters - TreeMap[List[I], Int] // illegal: type parameter not within bound - - F[Int, Boolean] // illegal: Int is not a type constructor - F[TreeMap, Int] // illegal: TreeMap takes two parameters, - // F expects a constructor taking one - G[S, Int] // illegal: S constrains its parameter to - // conform to String, - // G expects type constructor with a parameter - // that conforms to Int - ``` +F[List, Int] +G[S, String] +``` + +###### Example: ill-formed types + +Given the [above type definitions](example-parameterized-types), +the following types are ill-formed: + +``` +TreeMap[I] // illegal: wrong number of parameters +TreeMap[List[I], Int] // illegal: type parameter not within bound + +F[Int, Boolean] // illegal: Int is not a type constructor +F[TreeMap, Int] // illegal: TreeMap takes two parameters, + // F expects a constructor taking one +G[S, Int] // illegal: S constrains its parameter to + // conform to String, + // G expects type constructor with a parameter + // that conforms to Int +``` ### Tuple Types @@ -250,12 +255,13 @@ An annotated type $T$ `$a_1 , \ldots , a_n$` attaches [annotations](#user-defined-annotations) $a_1 , \ldots , a_n$ to the type $T$. -(@) The following type adds the `@suspendable` annotation to the type - `String`: +###### Example: annotated type - ``` - String @suspendable - ``` +The following type adds the `@suspendable` annotation to the type `String`: + +``` +String @suspendable +``` ### Compound Types @@ -287,7 +293,7 @@ any value parameter may only refer to type parameters or abstract types that are contained inside the refinement. That is, it must refer either to a type parameter of the method itself, or to a type definition within the refinement. This restriction does not apply to -the function's result type. +the method's result type. If no refinement is given, the empty refinement is implicitly added, i.e.\ `$T_1$ with … with $T_n$` is a shorthand for @@ -297,35 +303,37 @@ A compound type may also consist of just a refinement `{ $R$ }` with no preceding component types. Such a type is equivalent to `AnyRef{ R }`. -(@) The following example shows how to declare and use a function which - parameter's type contains a refinement with structural declarations. - - ``` - case class Bird (val name: String) extends Object { - def fly(height: Int) = … - … - } - case class Plane (val callsign: String) extends Object { - def fly(height: Int) = … - … - } - def takeoff( - runway: Int, - r: { val callsign: String; def fly(height: Int) }) = { - tower.print(r.callsign + " requests take-off on runway " + runway) - tower.read(r.callsign + " is clear for take-off") - r.fly(1000) - } - val bird = new Bird("Polly the parrot"){ val callsign = name } - val a380 = new Plane("TZ-987") - takeoff(42, bird) - takeoff(89, a380) - ``` - - Although `Bird` and `Plane` do not share any parent class other than - `Object`, the parameter _r_ of function `takeoff` is defined using a - refinement with structural declarations to accept any object that declares - a value `callsign` and a `fly` function. +###### Example: structural refinement in a method's parameter type + +The following example shows how to declare and use a method which +a parameter type that contains a refinement with structural declarations. + +``` +case class Bird (val name: String) extends Object { + def fly(height: Int) = … +… +} +case class Plane (val callsign: String) extends Object { + def fly(height: Int) = … +… +} +def takeoff( + runway: Int, + r: { val callsign: String; def fly(height: Int) }) = { + tower.print(r.callsign + " requests take-off on runway " + runway) + tower.read(r.callsign + " is clear for take-off") + r.fly(1000) +} +val bird = new Bird("Polly the parrot"){ val callsign = name } +val a380 = new Plane("TZ-987") +takeoff(42, bird) +takeoff(89, a380) +``` + +Although `Bird` and `Plane` do not share any parent class other than +`Object`, the parameter _r_ of method `takeoff` is defined using a +refinement with structural declarations to accept any object that declares +a value `callsign` and a `fly` method. ### Infix Types @@ -495,54 +503,60 @@ or [tuple types](#tuple-types). Their expansion is then the expansion in the equivalent parameterized type. -(@) Assume the class definitions - - ``` - class Ref[T] - abstract class Outer { type T } . - ``` +###### Example: existential types - Here are some examples of existential types: - - ``` - Ref[T] forSome { type T <: java.lang.Number } - Ref[x.T] forSome { val x: Outer } - Ref[x_type # T] forSome { type x_type <: Outer with Singleton } - ``` - - The last two types in this list are equivalent. - An alternative formulation of the first type above using wildcard syntax is: - - ``` - Ref[_ <: java.lang.Number] - ``` +Assume the class definitions -(@) The type `List[List[_]]` is equivalent to the existential type - - ``` - List[List[t] forSome { type t }] . - ``` +``` +class Ref[T] +abstract class Outer { type T } . +``` -(@) Assume a covariant type - - ``` - class List[+T] - ``` +Here are some examples of existential types: - The type - - ``` - List[T] forSome { type T <: java.lang.Number } - ``` +``` +Ref[T] forSome { type T <: java.lang.Number } +Ref[x.T] forSome { val x: Outer } +Ref[x_type # T] forSome { type x_type <: Outer with Singleton } +``` + +The last two types in this list are equivalent. +An alternative formulation of the first type above using wildcard syntax is: - is equivalent (by simplification rule 4 above) to +``` +Ref[_ <: java.lang.Number] +``` + +###### Example: abbreviating an existential type with the underscore + +The type `List[List[_]]` is equivalent to the existential type + +``` +List[List[t] forSome { type t }] . +``` + +###### Example: existential type equivalence + +Assume a covariant type - ``` - List[java.lang.Number] forSome { type T <: java.lang.Number } - ``` +``` +class List[+T] +``` + +The type - which is in turn equivalent (by simplification rules 2 and 3 above) to - `List[java.lang.Number]`. +``` +List[T] forSome { type T <: java.lang.Number } +``` + +is equivalent (by simplification rule 4 above) to + +``` +List[java.lang.Number] forSome { type T <: java.lang.Number } +``` + +which is in turn equivalent (by simplification rules 2 and 3 above) to +`List[java.lang.Number]`. ## Non-Value Types @@ -573,21 +587,23 @@ Method types do not exist as types of values. If a method name is used as a value, its type is [implicitly converted](#implicit-conversions) to a corresponding function type. -(@) The declarations - - ``` - def a: Int - def b (x: Int): Boolean - def c (x: Int) (y: String, z: String): String - ``` +###### Example - produce the typings +The declarations - ``` - a: => Int - b: (Int) Boolean - c: (Int) (String, String) String - ``` +``` +def a: Int +def b (x: Int): Boolean +def c (x: Int) (y: String, z: String): String +``` + +produce the typings + +``` +a: => Int +b: (Int) Boolean +c: (Int) (String, String) String +``` ### Polymorphic Method Types @@ -601,19 +617,21 @@ take type arguments `$S_1 , \ldots , S_n$` which `$L_1 , \ldots , L_n$` and the upper bounds `$U_1 , \ldots , U_n$` and that yield results of type $T$. -(@) The declarations +###### Example - ``` - def empty[A]: List[A] - def union[A <: Comparable[A]] (x: Set[A], xs: Set[A]): Set[A] - ``` +The declarations - produce the typings +``` +def empty[A]: List[A] +def union[A <: Comparable[A]] (x: Set[A], xs: Set[A]): Set[A] +``` + +produce the typings - ``` - empty : [A >: Nothing <: Any] List[A] - union : [A >: Nothing <: Comparable[A]] (x: Set[A], xs: Set[A]) Set[A] . - ``` +``` +empty : [A >: Nothing <: Any] List[A] +union : [A >: Nothing <: Comparable[A]] (x: Set[A], xs: Set[A]) Set[A] . +``` ### Type Constructors @@ -624,17 +642,19 @@ represents a type that is expected by a [abstract type constructor binding](#type-declarations-and-type-aliases) with the corresponding type parameter clause. -(@) Consider this fragment of the `Iterable[+X]` class: +###### Example + +Consider this fragment of the `Iterable[+X]` class: - ``` - trait Iterable[+X] { - def flatMap[newType[+X] <: Iterable[X], S](f: X => newType[S]): newType[S] - } - ``` +``` +trait Iterable[+X] { + def flatMap[newType[+X] <: Iterable[X], S](f: X => newType[S]): newType[S] +} +``` - Conceptually, the type constructor `Iterable` is a name for the - anonymous type `[+X] Iterable[X]`, which may be passed to the - `newType` type constructor parameter in `flatMap`. +Conceptually, the type constructor `Iterable` is a name for the +anonymous type `[+X] Iterable[X]`, which may be passed to the +`newType` type constructor parameter in `flatMap`. <!-- ### Overloaded Types @@ -644,7 +664,7 @@ same name, we model An overloaded type consisting of type alternatives $T_1 \commadots T_n (n \geq 2)$ is denoted internally $T_1 \overload \ldots \overload T_n$. -(@) The definitions +###### Example: The definitions ``` def println: Unit def println(s: String): Unit = $\ldots$ @@ -662,7 +682,7 @@ println: => Unit $\overload$ [A] (A) (A => String) Unit ``` -(@) The definitions +###### Example: The definitions ``` def f(x: T): T = $\ldots$ val f = 0 diff --git a/06-basic-declarations-and-definitions.md b/06-basic-declarations-and-definitions.md index 5d8f6aee78..b8eb226d3d 100644 --- a/06-basic-declarations-and-definitions.md +++ b/06-basic-declarations-and-definitions.md @@ -160,24 +160,26 @@ val $x$ = $e$ match { case $p$ => $x$ } $e$ match { case $p$ => ()} ``` -(@) The following are examples of value definitions +###### Example - ``` - val pi = 3.1415 - val pi: Double = 3.1415 // equivalent to first definition - val Some(x) = f() // a pattern definition - val x :: xs = mylist // an infix pattern definition - ``` +The following are examples of value definitions - The last two definitions have the following expansions. +``` +val pi = 3.1415 +val pi: Double = 3.1415 // equivalent to first definition +val Some(x) = f() // a pattern definition +val x :: xs = mylist // an infix pattern definition +``` + +The last two definitions have the following expansions. - ``` - val x = f() match { case Some(x) => x } +``` +val x = f() match { case Some(x) => x } - val x$\$$ = mylist match { case x :: xs => (x, xs) } - val x = x$\$$._1 - val xs = x$\$$._2 - ``` +val x$\$$ = mylist match { case x :: xs => (x, xs) } +val x = x$\$$._1 +val xs = x$\$$._2 +``` The name of any declared or defined value may not end in `_=`. @@ -253,35 +255,37 @@ The template then has these getter and setter functions as members, whereas the original variable cannot be accessed directly as a template member. -(@) The following example shows how _properties_ can be - simulated in Scala. It defines a class `TimeOfDayVar` of time - values with updatable integer fields representing hours, minutes, and - seconds. Its implementation contains tests that allow only legal - values to be assigned to these fields. The user code, on the other - hand, accesses these fields just like normal variables. - - ``` - class TimeOfDayVar { - private var h: Int = 0 - private var m: Int = 0 - private var s: Int = 0 - - def hours = h - def hours_= (h: Int) = if (0 <= h && h < 24) this.h = h - else throw new DateError() - - def minutes = m - def minutes_= (m: Int) = if (0 <= m && m < 60) this.m = m - else throw new DateError() - - def seconds = s - def seconds_= (s: Int) = if (0 <= s && s < 60) this.s = s - else throw new DateError() - } - val d = new TimeOfDayVar - d.hours = 8; d.minutes = 30; d.seconds = 0 - d.hours = 25 // throws a DateError exception - ``` +###### Example + +The following example shows how _properties_ can be +simulated in Scala. It defines a class `TimeOfDayVar` of time +values with updatable integer fields representing hours, minutes, and +seconds. Its implementation contains tests that allow only legal +values to be assigned to these fields. The user code, on the other +hand, accesses these fields just like normal variables. + +``` +class TimeOfDayVar { + private var h: Int = 0 + private var m: Int = 0 + private var s: Int = 0 + + def hours = h + def hours_= (h: Int) = if (0 <= h && h < 24) this.h = h + else throw new DateError() + + def minutes = m + def minutes_= (m: Int) = if (0 <= m && m < 60) this.m = m + else throw new DateError() + + def seconds = s + def seconds_= (s: Int) = if (0 <= s && s < 60) this.s = s + else throw new DateError() +} +val d = new TimeOfDayVar +d.hours = 8; d.minutes = 30; d.seconds = 0 +d.hours = 25 // throws a DateError exception +``` A variable declaration `var $x_1 , \ldots , x_n$: $T$` is a shorthand for the @@ -342,51 +346,55 @@ That is, the type $T$ in a type alias `type $t$[$\mathit{tps}\,$] = $T$` may not refer directly or indirectly to the name $t$. It is also an error if an abstract type is directly or indirectly its own upper or lower bound. -(@) The following are legal type declarations and definitions: +###### Example + +The following are legal type declarations and definitions: - ``` - type IntList = List[Integer] - type T <: Comparable[T] - type Two[A] = Tuple2[A, A] - type MyCollection[+X] <: Iterable[X] - ``` +``` +type IntList = List[Integer] +type T <: Comparable[T] +type Two[A] = Tuple2[A, A] +type MyCollection[+X] <: Iterable[X] +``` - The following are illegal: +The following are illegal: - ``` - type Abs = Comparable[Abs] // recursive type alias +``` +type Abs = Comparable[Abs] // recursive type alias - type S <: T // S, T are bounded by themselves. - type T <: S +type S <: T // S, T are bounded by themselves. +type T <: S - type T >: Comparable[T.That] // Cannot select from T. - // T is a type, not a value - type MyCollection <: Iterable // Type constructor members must explicitly - // state their type parameters. - ``` +type T >: Comparable[T.That] // Cannot select from T. + // T is a type, not a value +type MyCollection <: Iterable // Type constructor members must explicitly + // state their type parameters. +``` If a type alias `type $t$[$\mathit{tps}\,$] = $S$` refers to a class type $S$, the name $t$ can also be used as a constructor for objects of type $S$. -(@) The `Predef` object contains a definition which establishes `Pair` - as an alias of the parameterized class `Tuple2`: +###### Example - ``` - type Pair[+A, +B] = Tuple2[A, B] - object Pair { - def apply[A, B](x: A, y: B) = Tuple2(x, y) - def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x) - } - ``` +The `Predef` object contains a definition which establishes `Pair` +as an alias of the parameterized class `Tuple2`: + +``` +type Pair[+A, +B] = Tuple2[A, B] +object Pair { + def apply[A, B](x: A, y: B) = Tuple2(x, y) + def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x) +} +``` - As a consequence, for any two types $S$ and $T$, the type - `Pair[$S$, $T\,$]` is equivalent to the type `Tuple2[$S$, $T\,$]`. - `Pair` can also be used as a constructor instead of `Tuple2`, as in: +As a consequence, for any two types $S$ and $T$, the type +`Pair[$S$, $T\,$]` is equivalent to the type `Tuple2[$S$, $T\,$]`. +`Pair` can also be used as a constructor instead of `Tuple2`, as in: - ``` - val x: Pair[Int, String] = new Pair(1, "abc") - ``` +``` +val x: Pair[Int, String] = new Pair(1, "abc") +``` ## Type Parameters @@ -428,28 +436,29 @@ A type constructor parameter adds a nested type parameter clause to the type par The above scoping restrictions are generalized to the case of nested type parameter clauses, which declare higher-order type parameters. Higher-order type parameters (the type parameters of a type parameter $t$) are only visible in their immediately surrounding parameter clause (possibly including clauses at a deeper nesting level) and in the bounds of $t$. Therefore, their names must only be pairwise different from the names of other visible parameters. Since the names of higher-order type parameters are thus often irrelevant, they may be denoted with a ‘_’, which is nowhere visible. -(@) Here are some well-formed type parameter clauses: +###### Example +Here are some well-formed type parameter clauses: - ``` - [S, T] - [@specialized T, U] - [Ex <: Throwable] - [A <: Comparable[B], B <: A] - [A, B >: A, C >: A <: B] - [M[X], N[X]] - [M[_], N[_]] // equivalent to previous clause - [M[X <: Bound[X]], Bound[_]] - [M[+X] <: Iterable[X]] - ``` +``` +[S, T] +[@specialized T, U] +[Ex <: Throwable] +[A <: Comparable[B], B <: A] +[A, B >: A, C >: A <: B] +[M[X], N[X]] +[M[_], N[_]] // equivalent to previous clause +[M[X <: Bound[X]], Bound[_]] +[M[+X] <: Iterable[X]] +``` - The following type parameter clauses are illegal: +The following type parameter clauses are illegal: - ``` - [A >: A] // illegal, `A' has itself as bound - [A <: B, B <: C, C <: A] // illegal, `A' has itself as bound - [A, B, C >: A <: B] // illegal lower bound `A' of `C' does - // not conform to upper bound `B'. - ``` +``` +[A >: A] // illegal, `A' has itself as bound +[A <: B, B <: C, C <: A] // illegal, `A' has itself as bound +[A, B, C >: A <: B] // illegal lower bound `A' of `C' does + // not conform to upper bound `B'. +``` ## Variance Annotations @@ -502,75 +511,78 @@ References to the type parameters in checked for their variance position. In these members the type parameter may appear anywhere without restricting its legal variance annotations. -(@) The following variance annotation is legal. - - ``` - abstract class P[+A, +B] { - def fst: A; def snd: B - } - ``` - - With this variance annotation, type instances - of $P$ subtype covariantly with respect to their arguments. - For instance, - - ``` - P[IOException, String] <: P[Throwable, AnyRef] - ``` - - If the members of $P$ are mutable variables, - the same variance annotation becomes illegal. - - ``` - abstract class Q[+A, +B](x: A, y: B) { - var fst: A = x // **** error: illegal variance: - var snd: B = y // `A', `B' occur in invariant position. - } - ``` - - If the mutable variables are object-private, the class definition - becomes legal again: - - ``` - abstract class R[+A, +B](x: A, y: B) { - private[this] var fst: A = x // OK - private[this] var snd: B = y // OK - } - ``` - -(@) The following variance annotation is illegal, since $a$ appears - in contravariant position in the parameter of `append`: - - ``` - abstract class Sequence[+A] { - def append(x: Sequence[A]): Sequence[A] - // **** error: illegal variance: - // `A' occurs in contravariant position. - } - ``` - - The problem can be avoided by generalizing the type of `append` - by means of a lower bound: - - ``` - abstract class Sequence[+A] { - def append[B >: A](x: Sequence[B]): Sequence[B] - } - ``` - -(@) Here is a case where a contravariant type parameter is useful. - - ``` - abstract class OutputChannel[-A] { - def write(x: A): Unit - } - ``` - - With that annotation, we have that - `OutputChannel[AnyRef]` conforms to `OutputChannel[String]`. - That is, a - channel on which one can write any object can substitute for a channel - on which one can write only strings. +###### Example +The following variance annotation is legal. + +``` +abstract class P[+A, +B] { + def fst: A; def snd: B +} +``` + +With this variance annotation, type instances +of $P$ subtype covariantly with respect to their arguments. +For instance, + +``` +P[IOException, String] <: P[Throwable, AnyRef] +``` + +If the members of $P$ are mutable variables, +the same variance annotation becomes illegal. + +``` +abstract class Q[+A, +B](x: A, y: B) { + var fst: A = x // **** error: illegal variance: + var snd: B = y // `A', `B' occur in invariant position. +} +``` + +If the mutable variables are object-private, the class definition +becomes legal again: + +``` +abstract class R[+A, +B](x: A, y: B) { + private[this] var fst: A = x // OK + private[this] var snd: B = y // OK +} +``` + +###### Example + +The following variance annotation is illegal, since $a$ appears +in contravariant position in the parameter of `append`: + +``` +abstract class Sequence[+A] { + def append(x: Sequence[A]): Sequence[A] + // **** error: illegal variance: + // `A' occurs in contravariant position. +} +``` + +The problem can be avoided by generalizing the type of `append` +by means of a lower bound: + +``` +abstract class Sequence[+A] { + def append[B >: A](x: Sequence[B]): Sequence[B] +} +``` + +###### Example: Here is a case where a contravariant type parameter is useful. + +``` +abstract class OutputChannel[-A] { + def write(x: A): Unit +} +``` + +With that annotation, we have that +`OutputChannel[AnyRef]` conforms to `OutputChannel[String]`. +That is, a +channel on which one can write any object can substitute for a channel +on which one can write only strings. ## Function Declarations and Definitions @@ -636,21 +648,22 @@ parameter clauses, as well as the method return type and the function body, if they are given. Both type parameter names and value parameter names must be pairwise distinct. -(@) In the method +###### Example +In the method - ``` - def compare[T](a: T = 0)(b: T = a) = (a == b) - ``` +``` +def compare[T](a: T = 0)(b: T = a) = (a == b) +``` - the default expression `0` is type-checked with an undefined expected - type. When applying `compare()`, the default value `0` is inserted - and `T` is instantiated to `Int`. The methods computing the default - arguments have the form: +the default expression `0` is type-checked with an undefined expected +type. When applying `compare()`, the default value `0` is inserted +and `T` is instantiated to `Int`. The methods computing the default +arguments have the form: - ``` - def compare$\$$default$\$$1[T]: Int = 0 - def compare$\$$default$\$$2[T](a: T): T = a - ``` +``` +def compare$\$$default$\$$1[T]: Int = 0 +def compare$\$$default$\$$2[T](a: T): T = a +``` ### By-Name Parameters @@ -673,14 +686,15 @@ classes for which a `val` prefix is implicitly generated. The by-name modifier is also disallowed for [implicit parameters](#implicit-parameters). -(@) The declaration +###### Example +The declaration - ``` - def whileLoop (cond: => Boolean) (stat: => Unit): Unit - ``` +``` +def whileLoop (cond: => Boolean) (stat: => Unit): Unit +``` - indicates that both parameters of `whileLoop` are evaluated using - call-by-name. +indicates that both parameters of `whileLoop` are evaluated using +call-by-name. ### Repeated Parameters @@ -710,44 +724,45 @@ that application is taken to be It is not allowed to define any default arguments in a parameter section with a repeated parameter. -(@) The following method definition computes the sum of the squares of a - variable number of integer arguments. +###### Example +The following method definition computes the sum of the squares of a +variable number of integer arguments. - ``` - def sum(args: Int*) = { - var result = 0 - for (arg <- args) result += arg * arg - result - } - ``` +``` +def sum(args: Int*) = { + var result = 0 + for (arg <- args) result += arg * arg + result +} +``` - The following applications of this method yield `0`, `1`, - `6`, in that order. +The following applications of this method yield `0`, `1`, +`6`, in that order. - ``` - sum() - sum(1) - sum(1, 2, 3) - ``` +``` +sum() +sum(1) +sum(1, 2, 3) +``` - Furthermore, assume the definition: +Furthermore, assume the definition: - ``` - val xs = List(1, 2, 3) - ``` +``` +val xs = List(1, 2, 3) +``` - The following application of method `sum` is ill-formed: +The following application of method `sum` is ill-formed: - ``` - sum(xs) // ***** error: expected: Int, found: List[Int] - ``` +``` +sum(xs) // ***** error: expected: Int, found: List[Int] +``` - By contrast, the following application is well formed and yields again - the result `6`: +By contrast, the following application is well formed and yields again +the result `6`: - ``` - sum(xs: _*) - ``` +``` +sum(xs: _*) +``` ### Procedures @@ -769,27 +784,28 @@ and the equals sign are omitted; its defining expression must be a block. E.g., `def $f$($\mathit{ps}$) {$\mathit{stats}$}` is equivalent to `def $f$($\mathit{ps}$): Unit = {$\mathit{stats}$}`. -(@) Here is a declaration and a definition of a procedure named `write`: +###### Example +Here is a declaration and a definition of a procedure named `write`: - ``` - trait Writer { - def write(str: String) - } - object Terminal extends Writer { - def write(str: String) { System.out.println(str) } - } - ``` +``` +trait Writer { + def write(str: String) +} +object Terminal extends Writer { + def write(str: String) { System.out.println(str) } +} +``` - The code above is implicitly completed to the following code: +The code above is implicitly completed to the following code: - ``` - trait Writer { - def write(str: String): Unit - } - object Terminal extends Writer { - def write(str: String): Unit = { System.out.println(str) } - } - ``` +``` +trait Writer { + def write(str: String): Unit +} +object Terminal extends Writer { + def write(str: String): Unit = { System.out.println(str) } +} +``` ### Method Return Type Inference @@ -803,19 +819,20 @@ right-hand side of $m$ can be determined, which is then taken as the return type of $m$. Note that $R$ may be different from $R'$, as long as $R$ conforms to $R'$. -(@) Assume the following definitions: +###### Example +Assume the following definitions: - ``` - trait I { - def factorial(x: Int): Int - } - class C extends I { - def factorial(x: Int) = if (x == 0) 1 else x * factorial(x - 1) - } - ``` +``` +trait I { + def factorial(x: Int): Int +} +class C extends I { + def factorial(x: Int) = if (x == 0) 1 else x * factorial(x - 1) +} +``` - Here, it is OK to leave out the result type of `factorial` - in `C`, even though the method is recursive. +Here, it is OK to leave out the result type of `factorial` +in `C`, even though the method is recursive. @@ -901,23 +918,24 @@ An import clause with multiple import expressions sequence of import clauses `import $p_1$.$I_1$; $\ldots$; import $p_n$.$I_n$`. -(@) Consider the object definition: +###### Example +Consider the object definition: - ``` - object M { - def z = 0, one = 1 - def add(x: Int, y: Int): Int = x + y - } - ``` - Then the block +``` +object M { + def z = 0, one = 1 + def add(x: Int, y: Int): Int = x + y +} +``` - ``` - { import M.{one, z => zero, _}; add(zero, one) } - ``` +Then the block - is equivalent to the block +``` +{ import M.{one, z => zero, _}; add(zero, one) } +``` - ``` - { M.add(M.z, M.one) } - ``` +is equivalent to the block +``` +{ M.add(M.z, M.one) } +``` diff --git a/07-classes-and-objects.md b/07-classes-and-objects.md index 292f6eaa53..392da29d0f 100644 --- a/07-classes-and-objects.md +++ b/07-classes-and-objects.md @@ -87,19 +87,20 @@ A second form of self type annotation reads just `this: $S$ =>`. It prescribes the type $S$ for `this` without introducing an alias name for it. -(@) Consider the following class definitions: +###### Example +Consider the following class definitions: - ``` - class Base extends Object {} - trait Mixin extends Base {} - object O extends Mixin {} - ``` +``` +class Base extends Object {} +trait Mixin extends Base {} +object O extends Mixin {} +``` - In this case, the definition of `O` is expanded to: +In this case, the definition of `O` is expanded to: - ``` - object O extends Base with Mixin {} - ``` +``` +object O extends Base with Mixin {} +``` <!-- TODO: Make all references to Java generic --> @@ -203,42 +204,43 @@ linearization of this graph is defined as follows. > ``` -(@) Consider the following class definitions. +###### Example +Consider the following class definitions. - ``` - abstract class AbsIterator extends AnyRef { ... } - trait RichIterator extends AbsIterator { ... } - class StringIterator extends AbsIterator { ... } - class Iter extends StringIterator with RichIterator { ... } - ``` +``` +abstract class AbsIterator extends AnyRef { ... } +trait RichIterator extends AbsIterator { ... } +class StringIterator extends AbsIterator { ... } +class Iter extends StringIterator with RichIterator { ... } +``` - Then the linearization of class `Iter` is +Then the linearization of class `Iter` is - ``` - { Iter, RichIterator, StringIterator, AbsIterator, AnyRef, Any } - ``` +``` +{ Iter, RichIterator, StringIterator, AbsIterator, AnyRef, Any } +``` - 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 +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 - ``` - { StringIterator, AbsIterator, AnyRef, Any } - ``` +``` +{ StringIterator, AbsIterator, AnyRef, Any } +``` - which is a suffix of the linearization of its subclass `Iter`. - The same is not true for the linearization of mixins. - For instance, the linearization of `RichIterator` is +which is a suffix of the linearization of its subclass `Iter`. +The same is not true for the linearization of mixins. +For instance, the linearization of `RichIterator` is - ``` - { RichIterator, AbsIterator, AnyRef, Any } - ``` +``` +{ RichIterator, AbsIterator, AnyRef, Any } +``` - which is not a suffix of the linearization of `Iter`. +which is not a suffix of the linearization of `Iter`. ### Class Members @@ -306,18 +308,19 @@ Finally, a template is not allowed to contain two methods (directly defined or inherited) with the same name which both define default arguments. -(@) Consider the trait definitions: +###### Example +Consider the trait definitions: - ``` - trait A { def f: Int } - trait B extends A { def f: Int = 1 ; def g: Int = 2 ; def h: Int = 3 } - trait C extends A { override def f: Int = 4 ; def g: Int } - trait D extends B with C { def h: Int } - ``` +``` +trait A { def f: Int } +trait B extends A { def f: Int = 1 ; def g: Int = 2 ; def h: Int = 3 } +trait C extends A { override def f: Int = 4 ; def g: Int } +trait D extends B with C { def h: Int } +``` - Then trait `D` has a directly defined abstract member `h`. It - inherits member `f` from trait `C` and member `g` from - trait `B`. +Then trait `D` has a directly defined abstract member `h`. It +inherits member `f` from trait `C` and member `g` from +trait `B`. ### Overriding @@ -366,25 +369,27 @@ it is possible to add new defaults (if the corresponding parameter in the superclass does not have a default) or to override the defaults of the superclass (otherwise). -(@compounda) Consider the definitions: +###### Example: compound types - ``` - trait Root { type T <: Root } - trait A extends Root { type T <: A } - trait B extends Root { type T <: B } - trait C extends A with B - ``` +Consider the definitions: - Then the class definition `C` is not well-formed because the - binding of `T` in `C` is - `type T <: B`, - which fails to subsume the binding `type T <: A` of `T` - in type `A`. The problem can be solved by adding an overriding - definition of type `T` in class `C`: +``` +trait Root { type T <: Root } +trait A extends Root { type T <: A } +trait B extends Root { type T <: B } +trait C extends A with B +``` - ``` - class C extends A with B { type T <: C } - ``` +Then the class definition `C` is not well-formed because the +binding of `T` in `C` is +`type T <: B`, +which fails to subsume the binding `type T <: A` of `T` +in type `A`. The problem can be solved by adding an overriding +definition of type `T` in class `C`: + +``` +class C extends A with B { type T <: C } +``` ### Inheritance Closure @@ -444,31 +449,32 @@ definitions. Early definitions are evaluated in the order they are being defined before the superclass constructor of the template is called. -(@) Early definitions are particularly useful for - traits, which do not have normal constructor parameters. Example: +###### Example +Early definitions are particularly useful for +traits, which do not have normal constructor parameters. Example: - ``` - trait Greeting { - val name: String - val msg = "How are you, "+name - } - class C extends { - val name = "Bob" - } with Greeting { - println(msg) - } - ``` +``` +trait Greeting { + val name: String + val msg = "How are you, "+name +} +class C extends { + val name = "Bob" +} with Greeting { + println(msg) +} +``` + +In the code above, the field `name` is initialized before the +constructor of `Greeting` is called. Therefore, field `msg` in +class `Greeting` is properly initialized to `"How are you, Bob"`. + +If `name` had been initialized instead in `C`'s normal class +body, it would be initialized after the constructor of +`Greeting`. In that case, `msg` would be initialized to +`"How are you, <null>"`. - In the code above, the field `name` is initialized before the - constructor of `Greeting` is called. Therefore, field `msg` in - class `Greeting` is properly initialized to `"How are you, Bob"`. - If `name` had been initialized instead in `C`'s normal class - body, it would be initialized after the constructor of - `Greeting`. In that case, `msg` would be initialized to - `"How are you, <null>"`. - - ## Modifiers ``` @@ -609,53 +615,55 @@ the validity and meaning of a modifier are as follows. and a later access will retry to evaluate its right hand side. -(@) The following code illustrates the use of qualified private: +###### Example +The following code illustrates the use of qualified private: - ``` - package outerpkg.innerpkg - class Outer { - class Inner { - private[Outer] def f() - private[innerpkg] def g() - private[outerpkg] def h() - } - } - ``` +``` +package outerpkg.innerpkg +class Outer { + class Inner { + private[Outer] def f() + private[innerpkg] def g() + private[outerpkg] def h() + } +} +``` - Here, accesses to the method `f` can appear anywhere within - `OuterClass`, but not outside it. Accesses to method - `g` can appear anywhere within the package - `outerpkg.innerpkg`, as would be the case for - package-private methods in Java. Finally, accesses to method - `h` can appear anywhere within package `outerpkg`, - including packages contained in it. +Here, accesses to the method `f` can appear anywhere within +`OuterClass`, but not outside it. Accesses to method +`g` can appear anywhere within the package +`outerpkg.innerpkg`, as would be the case for +package-private methods in Java. Finally, accesses to method +`h` can appear anywhere within package `outerpkg`, +including packages contained in it. -(@) A useful idiom to prevent clients of a class from - constructing new instances of that class is to declare the class - `abstract` and `sealed`: +###### Example +A useful idiom to prevent clients of a class from +constructing new instances of that class is to declare the class +`abstract` and `sealed`: - ``` - object m { - abstract sealed class C (x: Int) { - def nextC = new C(x + 1) {} - } - val empty = new C(0) {} - } - ``` +``` +object m { + abstract sealed class C (x: Int) { + def nextC = new C(x + 1) {} + } + val empty = new C(0) {} +} +``` - For instance, in the code above clients can create instances of class - `m.C` only by calling the `nextC` method of an existing `m.C` - object; it is not possible for clients to create objects of class - `m.C` directly. Indeed the following two lines are both in error: +For instance, in the code above clients can create instances of class +`m.C` only by calling the `nextC` method of an existing `m.C` +object; it is not possible for clients to create objects of class +`m.C` directly. Indeed the following two lines are both in error: - ``` - new m.C(0) // **** error: C is abstract, so it cannot be instantiated. - new m.C(0) {} // **** error: illegal inheritance from sealed class. - ``` +``` +new m.C(0) // **** error: C is abstract, so it cannot be instantiated. +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}). +A similar access restriction can be achieved by marking the primary +constructor `private` (see \ref{ex:private-constr}). ## Class Definitions @@ -741,28 +749,27 @@ which when applied to parameters conforming to types $\mathit{ps}$ initializes instances of type `$c$[$\mathit{tps}\,$]` by evaluating the template $t$. -(@) The following example illustrates `val` and `var` - parameters of a class `C`: +###### Example +The following example illustrates `val` and `var` parameters of a class `C`: - ``` - class C(x: Int, val y: String, var z: List[String]) - val c = new C(1, "abc", List()) - c.z = c.y :: c.z - ``` +``` +class C(x: Int, val y: String, var z: List[String]) +val c = new C(1, "abc", List()) +c.z = c.y :: c.z +``` -(@privateconstr) The following class can be created only from its companion - module. +The following class can be created only from its companion module. - ``` - object Sensitive { - def makeSensitive(credentials: Certificate): Sensitive = - if (credentials == Admin) new Sensitive() - else throw new SecurityViolationException - } - class Sensitive private () { - ... - } - ``` +``` +object Sensitive { + def makeSensitive(credentials: Certificate): Sensitive = + if (credentials == Admin) new Sensitive() + else throw new SecurityViolationException +} +class Sensitive private () { + ... +} +``` ### Constructor Definitions @@ -817,21 +824,22 @@ invocation must refer to a constructor definition which precedes it primary constructor of the class). -(@) Consider the class definition +###### Example +Consider the class definition - ``` - class LinkedList[A]() { - var head = _ - var tail = null - def isEmpty = tail != null - def this(head: A) = { this(); this.head = head } - def this(head: A, tail: List[A]) = { this(head); this.tail = tail } - } - ``` +``` +class LinkedList[A]() { + var head = _ + var tail = null + def isEmpty = tail != null + def this(head: A) = { this(); this.head = head } + def this(head: A, tail: List[A]) = { this(head); this.tail = tail } +} +``` - This defines a class `LinkedList` with three constructors. The - second constructor constructs an singleton list, while the - third one constructs a list with a given head and tail. +This defines a class `LinkedList` with three constructors. The +second constructor constructs an singleton list, while the +third one constructs a list with a given head and tail. ## Case Classes @@ -924,46 +932,47 @@ class different from `AnyRef`. In particular: contains the name of the class and its elements. -(@) Here is the definition of abstract syntax for lambda calculus: +###### Example +Here is the definition of abstract syntax for lambda calculus: - ``` - class Expr - case class Var (x: String) extends Expr - case class Apply (f: Expr, e: Expr) extends Expr - case class Lambda(x: String, e: Expr) extends Expr - ``` +``` +class Expr +case class Var (x: String) extends Expr +case class Apply (f: Expr, e: Expr) extends Expr +case class Lambda(x: String, e: Expr) extends Expr +``` - This defines a class `Expr` with case classes - `Var`, `Apply` and `Lambda`. A call-by-value evaluator - for lambda expressions could then be written as follows. +This defines a class `Expr` with case classes +`Var`, `Apply` and `Lambda`. A call-by-value evaluator +for lambda expressions could then be written as follows. - ``` - type Env = String => Value - case class Value(e: Expr, env: Env) - - def eval(e: Expr, env: Env): Value = e match { - case Var (x) => - env(x) - case Apply(f, g) => - val Value(Lambda (x, e1), env1) = eval(f, env) - val v = eval(g, env) - eval (e1, (y => if (y == x) v else env1(y))) - case Lambda(_, _) => - Value(e, env) - } - ``` +``` +type Env = String => Value +case class Value(e: Expr, env: Env) + +def eval(e: Expr, env: Env): Value = e match { + case Var (x) => + env(x) + case Apply(f, g) => + val Value(Lambda (x, e1), env1) = eval(f, env) + val v = eval(g, env) + eval (e1, (y => if (y == x) v else env1(y))) + case Lambda(_, _) => + Value(e, env) +} +``` - It is possible to define further case classes that extend type - `Expr` in other parts of the program, for instance +It is possible to define further case classes that extend type +`Expr` in other parts of the program, for instance - ``` - case class Number(x: Int) extends Expr - ``` +``` +case class Number(x: Int) extends Expr +``` - This form of extensibility can be excluded by declaring the base class - `Expr` `sealed`; in this case, all classes that - directly extend `Expr` must be in the same source file as - `Expr`. +This form of extensibility can be excluded by declaring the base class +`Expr` `sealed`; in this case, all classes that +directly extend `Expr` must be in the same source file as +`Expr`. ### Traits @@ -992,83 +1001,85 @@ statically known at the time the trait is defined. If $D$ is not a trait, then its actual supertype is simply its least proper supertype (which is statically known). -(@comparable) The following trait defines the property - of being comparable to objects of some type. It contains an abstract - method `<` and default implementations of the other - comparison operators `<=`, `>`, and - `>=`. +###### Example: `Comparable` +The following trait defines the property +of being comparable to objects of some type. It contains an abstract +method `<` and default implementations of the other +comparison operators `<=`, `>`, and +`>=`. - ``` - trait Comparable[T <: Comparable[T]] { self: T => - def < (that: T): Boolean - def <=(that: T): Boolean = this < that || this == that - def > (that: T): Boolean = that < this - def >=(that: T): Boolean = that <= this - } - ``` +``` +trait Comparable[T <: Comparable[T]] { self: T => + def < (that: T): Boolean + def <=(that: T): Boolean = this < that || this == that + def > (that: T): Boolean = that < this + def >=(that: T): Boolean = that <= this +} +``` -(@) Consider an abstract class `Table` that implements maps - from a type of keys `A` to a type of values `B`. The class - has a method `set` to enter a new key / value pair into the table, - and a method `get` that returns an optional value matching a - given key. Finally, there is a method `apply` which is like - `get`, except that it returns a given default value if the table - is undefined for the given key. This class is implemented as follows. +###### Example +Consider an abstract class `Table` that implements maps +from a type of keys `A` to a type of values `B`. The class +has a method `set` to enter a new key / value pair into the table, +and a method `get` that returns an optional value matching a +given key. Finally, there is a method `apply` which is like +`get`, except that it returns a given default value if the table +is undefined for the given key. This class is implemented as follows. - ``` - abstract class Table[A, B](defaultValue: B) { - def get(key: A): Option[B] - def set(key: A, value: B) - def apply(key: A) = get(key) match { - case Some(value) => value - case None => defaultValue - } - } - ``` +``` +abstract class Table[A, B](defaultValue: B) { + def get(key: A): Option[B] + def set(key: A, value: B) + def apply(key: A) = get(key) match { + case Some(value) => value + case None => defaultValue + } +} +``` - Here is a concrete implementation of the `Table` class. +Here is a concrete implementation of the `Table` class. - ``` - class ListTable[A, B](defaultValue: B) extends Table[A, B](defaultValue) { - private var elems: List[(A, B)] - def get(key: A) = elems.find(._1.==(key)).map(._2) - def set(key: A, value: B) = { elems = (key, value) :: elems } - } - ``` +``` +class ListTable[A, B](defaultValue: B) extends Table[A, B](defaultValue) { + private var elems: List[(A, B)] + def get(key: A) = elems.find(._1.==(key)).map(._2) + def set(key: A, value: B) = { elems = (key, value) :: elems } +} +``` - Here is a trait that prevents concurrent access to the - `get` and `set` operations of its parent class: +Here is a trait that prevents concurrent access to the +`get` and `set` operations of its parent class: - ``` - trait SynchronizedTable[A, B] extends Table[A, B] { - abstract override def get(key: A): B = - synchronized { super.get(key) } - abstract override def set((key: A, value: B) = - synchronized { super.set(key, value) } - } - ``` +``` +trait SynchronizedTable[A, B] extends Table[A, B] { + abstract override def get(key: A): B = + synchronized { super.get(key) } + abstract override def set((key: A, value: B) = + synchronized { super.set(key, value) } +} +``` - Note that `SynchronizedTable` does not pass an argument to - its superclass, `Table`, even though `Table` is defined with a - formal parameter. Note also that the `super` calls - in `SynchronizedTable`'s `get` and `set` methods - statically refer to abstract methods in class `Table`. This is - legal, as long as the calling method is labeled - [`abstract override`](#modifiers). +Note that `SynchronizedTable` does not pass an argument to +its superclass, `Table`, even though `Table` is defined with a +formal parameter. Note also that the `super` calls +in `SynchronizedTable`'s `get` and `set` methods +statically refer to abstract methods in class `Table`. This is +legal, as long as the calling method is labeled +[`abstract override`](#modifiers). - Finally, the following mixin composition creates a synchronized list - table with strings as keys and integers as values and with a default - value `0`: +Finally, the following mixin composition creates a synchronized list +table with strings as keys and integers as values and with a default +value `0`: - ``` - object MyTable extends ListTable[String, Int](0) with SynchronizedTable - ``` +``` +object MyTable extends ListTable[String, Int](0) with SynchronizedTable +``` - The object `MyTable` inherits its `get` and `set` - method from `SynchronizedTable`. The `super` calls in these - methods are re-bound to refer to the corresponding implementations in - `ListTable`, which is the actual supertype of `SynchronizedTable` - in `MyTable`. +The object `MyTable` inherits its `get` and `set` +method from `SynchronizedTable`. The `super` calls in these +methods are re-bound to refer to the corresponding implementations in +`ListTable`, which is the actual supertype of `SynchronizedTable` +in `MyTable`. ## Object Definitions @@ -1117,31 +1128,32 @@ cannot be because variable and method definition cannot appear on the top-level outside of a [package object](#package-objects). Instead, top-level objects are translated to static fields. -(@) Classes in Scala do not have static members; however, an equivalent - effect can be achieved by an accompanying object definition - E.g. +###### Example +Classes in Scala do not have static members; however, an equivalent +effect can be achieved by an accompanying object definition +E.g. - ``` - abstract class Point { - val x: Double - val y: Double - def isOrigin = (x == 0.0 && y == 0.0) - } - object Point { - val origin = new Point() { val x = 0.0; val y = 0.0 } - } - ``` +``` +abstract class Point { + val x: Double + val y: Double + def isOrigin = (x == 0.0 && y == 0.0) +} +object Point { + val origin = new Point() { val x = 0.0; val y = 0.0 } +} +``` - This defines a class `Point` and an object `Point` which - contains `origin` as a member. Note that the double use of the - name `Point` is legal, since the class definition defines the - name `Point` in the type name space, whereas the object - definition defines a name in the term namespace. +This defines a class `Point` and an object `Point` which +contains `origin` as a member. Note that the double use of the +name `Point` is legal, since the class definition defines the +name `Point` in the type name space, whereas the object +definition defines a name in the term namespace. - This technique is applied by the Scala compiler when interpreting a - Java class with static members. Such a class $C$ is conceptually seen - as a pair of a Scala class that contains all instance members of $C$ - and a Scala object that contains all static members of $C$. +This technique is applied by the Scala compiler when interpreting a +Java class with static members. Such a class $C$ is conceptually seen +as a pair of a Scala class that contains all instance members of $C$ +and a Scala object that contains all static members of $C$. Generally, a _companion module_ of a class is an object which has the same name as the class and is defined in the same scope and diff --git a/08-expressions.md b/08-expressions.md index 1fe82e9b95..4adf23c63e 100644 --- a/08-expressions.md +++ b/08-expressions.md @@ -209,32 +209,33 @@ to the type or method of $x$ in the parent trait of $C$ whose simple name is $T$. That member must be uniquely defined. If it is a method, it must be concrete. -(@super) Consider the following class definitions +###### Example: `super` +Consider the following class definitions - ``` - class Root { def x = "Root" } - class A extends Root { override def x = "A" ; def superA = super.x } - trait B extends Root { override def x = "B" ; def superB = super.x } - class C extends Root with B { - override def x = "C" ; def superC = super.x - } - class D extends A with B { - override def x = "D" ; def superD = super.x - } - ``` +``` +class Root { def x = "Root" } +class A extends Root { override def x = "A" ; def superA = super.x } +trait B extends Root { override def x = "B" ; def superB = super.x } +class C extends Root with B { + override def x = "C" ; def superC = super.x +} +class D extends A with B { + override def x = "D" ; def superD = super.x +} +``` - The linearization of class `C` is `{C, B, Root}` and - the linearization of class `D` is `{D, B, A, Root}`. - Then we have: +The linearization of class `C` is `{C, B, Root}` and +the linearization of class `D` is `{D, B, A, Root}`. +Then we have: - ``` - (new A).superA == "Root", - (new C).superB = "Root", (new C).superC = "B", - (new D).superA == "Root", (new D).superB = "A", (new D).superD = "B", - ``` +``` +(new A).superA == "Root", + (new C).superB = "Root", (new C).superC = "B", +(new D).superA == "Root", (new D).superB = "A", (new D).superD = "B", +``` - Note that the `superB` function returns different results - depending on whether `B` is mixed in with class `Root` or `A`. +Note that the `superB` function returns different results +depending on whether `B` is mixed in with class `Root` or `A`. ## Function Applications @@ -320,27 +321,28 @@ run-time stack. However, if a local function or a final method calls itself as its last action, the call is executed using the stack-frame of the caller. -(@) Assume the following function which computes the sum of a - variable number of arguments: +###### Example +Assume the following function which computes the sum of a +variable number of arguments: - ``` - def sum(xs: Int*) = (0 /: xs) ((x, y) => x + y) - ``` +``` +def sum(xs: Int*) = (0 /: xs) ((x, y) => x + y) +``` - Then +Then - ``` - sum(1, 2, 3, 4) - sum(List(1, 2, 3, 4): _*) - ``` +``` +sum(1, 2, 3, 4) +sum(List(1, 2, 3, 4): _*) +``` - both yield `10` as result. On the other hand, +both yield `10` as result. On the other hand, - ``` - sum(List(1, 2, 3, 4)) - ``` +``` +sum(List(1, 2, 3, 4)) +``` - would not typecheck. +would not typecheck. ### Named and Default Arguments @@ -432,18 +434,19 @@ parameterless method or call-by-name parameter of type `() => $T$`, which evaluates $e$ when it is applied to the empty parameterlist `()`. -(@) The method values in the left column are each equivalent to the - [anonymous functions](#anonymous-functions) on their right. +###### Example +The method values in the left column are each equivalent to the +[anonymous functions](#anonymous-functions) on their right. - ------------------------------ ----------------------------------------------------- - `Math.sin _` `x => Math.sin(x)` - `Array.range _` `(x1, x2) => Array.range(x1, x2)` - `List.map2 _` `(x1, x2) => (x3) => List.map2(x1, x2)(x3)` - `List.map2(xs, ys)_` `x => List.map2(xs, ys)(x)` - ------------------------------ ----------------------------------------------------- +|------------------------------ | --------------------------------------------| +|`Math.sin _` | `x => Math.sin(x)` | +|`Array.range _` | `(x1, x2) => Array.range(x1, x2)` | +|`List.map2 _` | `(x1, x2) => (x3) => List.map2(x1, x2)(x3)` | +|`List.map2(xs, ys)_` | `x => List.map2(xs, ys)(x)` | +|------------------------------ | --------------------------------------------| - Note that a space is necessary between a method name and the trailing underscore - because otherwise the underscore would be considered part of the name. +Note that a space is necessary between a method name and the trailing underscore +because otherwise the underscore would be considered part of the name. ## Type Applications @@ -531,25 +534,26 @@ types: If `{$D$}` is a class body, then `new {$D$}` is equivalent to the general instance creation expression `new AnyRef{$D$}`. -(@) Consider the following structural instance creation expression: +###### Example +Consider the following structural instance creation expression: - ``` - new { def getName() = "aaron" } - ``` +``` +new { def getName() = "aaron" } +``` - This is a shorthand for the general instance creation expression +This is a shorthand for the general instance creation expression - ``` - new AnyRef{ def getName() = "aaron" } - ``` +``` +new AnyRef{ def getName() = "aaron" } +``` - The latter is in turn a shorthand for the block +The latter is in turn a shorthand for the block - ``` - { class anon\$X extends AnyRef{ def getName() = "aaron" }; new anon\$X } - ``` +``` +{ class anon\$X extends AnyRef{ def getName() = "aaron" }; new anon\$X } +``` - where `anon\$X` is some freshly created name. +where `anon\$X` is some freshly created name. ## Blocks @@ -597,22 +601,23 @@ Evaluation of the block entails evaluation of its statement sequence, followed by an evaluation of the final expression $e$, which defines the result of the block. -(@) Assuming a class `Ref[T](x: T)`, the block +###### Example +Assuming a class `Ref[T](x: T)`, the block - ``` - { class C extends B {$\ldots$} ; new Ref(new C) } - ``` +``` +{ class C extends B {$\ldots$} ; new Ref(new C) } +``` - has the type `Ref[_1] forSome { type _1 <: B }`. - The block +has the type `Ref[_1] forSome { type _1 <: B }`. +The block - ``` - { class C extends B {$\ldots$} ; new C } - ``` +``` +{ class C extends B {$\ldots$} ; new C } +``` - simply has type `B`, because with the rules [here](#simplification-rules) - the existentially quantified type - `_1 forSome { type _1 <: B }` can be simplified to `B`. +simply has type `B`, because with the rules [here](#simplification-rules) +the existentially quantified type +`_1 forSome { type _1 <: B }` can be simplified to `B`. ## Prefix, Infix, and Postfix Operations @@ -760,13 +765,14 @@ The typed expression $e: T$ has type $T$. The type of expression $e$ is expected to conform to $T$. The result of the expression is the value of $e$ converted to type $T$. -(@) Here are examples of well-typed and illegally typed expressions. +###### Example +Here are examples of well-typed and ill-typed expressions. - ``` - 1: Int // legal, of type Int - 1: Long // legal, of type Long - // 1: string // ***** illegal - ``` +``` +1: Int // legal, of type Int +1: Long // legal, of type Long +// 1: string // ***** illegal +``` ## Annotated Expressions @@ -804,63 +810,66 @@ left of the ‘`=`’ operator is interpreted as `$f.$update($\mathit{args}$, $e\,$)`, i.e.\ the invocation of an `update` function defined by $f$. -(@) Here are some assignment expressions and their equivalent expansions. +###### Example +Here are some assignment expressions and their equivalent expansions. - -------------------------- --------------------- - `x.f = e` x.f_=(e) - `x.f() = e` x.f.update(e) - `x.f(i) = e` x.f.update(i, e) - `x.f(i, j) = e` x.f.update(i, j, e) - -------------------------- --------------------- +-------------------------- --------------------- +`x.f = e` x.f_=(e) +`x.f() = e` x.f.update(e) +`x.f(i) = e` x.f.update(i, e) +`x.f(i, j) = e` x.f.update(i, j, e) +-------------------------- --------------------- -(@imp-mat-mul) Here is the usual imperative code for matrix multiplication. +###### Example: imperative matrix multiplication - ``` - def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = { - val zss: Array[Array[Double]] = new Array(xss.length, yss(0).length) - var i = 0 - while (i < xss.length) { - var j = 0 - while (j < yss(0).length) { - var acc = 0.0 - var k = 0 - while (k < yss.length) { - acc = acc + xss(i)(k) * yss(k)(j) - k += 1 - } - zss(i)(j) = acc - j += 1 - } - i += 1 +Here is the usual imperative code for matrix multiplication. + +``` +def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = { + val zss: Array[Array[Double]] = new Array(xss.length, yss(0).length) + var i = 0 + while (i < xss.length) { + var j = 0 + while (j < yss(0).length) { + var acc = 0.0 + var k = 0 + while (k < yss.length) { + acc = acc + xss(i)(k) * yss(k)(j) + k += 1 } - zss + zss(i)(j) = acc + j += 1 } - ``` + i += 1 + } + zss +} +``` - Desugaring the array accesses and assignments yields the following - expanded version: +Desugaring the array accesses and assignments yields the following +expanded version: - ``` - def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = { - val zss: Array[Array[Double]] = new Array(xss.length, yss.apply(0).length) - var i = 0 - while (i < xss.length) { - var j = 0 - while (j < yss.apply(0).length) { - var acc = 0.0 - var k = 0 - while (k < yss.length) { - acc = acc + xss.apply(i).apply(k) * yss.apply(k).apply(j) - k += 1 - } - zss.apply(i).update(j, acc) - j += 1 - } - i += 1 +``` +def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = { + val zss: Array[Array[Double]] = new Array(xss.length, yss.apply(0).length) + var i = 0 + while (i < xss.length) { + var j = 0 + while (j < yss.apply(0).length) { + var acc = 0.0 + var k = 0 + while (k < yss.length) { + acc = acc + xss.apply(i).apply(k) * yss.apply(k).apply(j) + k += 1 } - zss + zss.apply(i).update(j, acc) + j += 1 } - ``` + i += 1 + } + zss +} +``` ## Conditional Expressions @@ -1007,64 +1016,66 @@ comprehensions have been eliminated. ``` -(@) The following code produces all pairs of numbers between $1$ and $n-1$ - whose sums are prime. +###### Example +The following code produces all pairs of numbers between $1$ and $n-1$ +whose sums are prime. - ``` - for { i <- 1 until n - j <- 1 until i - if isPrime(i+j) - } yield (i, j) - ``` +``` +for { i <- 1 until n + j <- 1 until i + if isPrime(i+j) +} yield (i, j) +``` - The for comprehension is translated to: +The for comprehension is translated to: - ``` - (1 until n) - .flatMap { - case i => (1 until i) - .withFilter { j => isPrime(i+j) } - .map { case j => (i, j) } } - ``` +``` +(1 until n) + .flatMap { + case i => (1 until i) + .withFilter { j => isPrime(i+j) } + .map { case j => (i, j) } } +``` -(@) For comprehensions can be used to express vector - and matrix algorithms concisely. - For instance, here is a function to compute the transpose of a given matrix: +###### Example +For comprehensions can be used to express vector +and matrix algorithms concisely. +For instance, here is a function to compute the transpose of a given matrix: - <!-- see test/files/run/t0421.scala --> +<!-- see test/files/run/t0421.scala --> - ``` - def transpose[A](xss: Array[Array[A]]) = { - for (i <- Array.range(0, xss(0).length)) yield - for (xs <- xss) yield xs(i) - } - ``` +``` +def transpose[A](xss: Array[Array[A]]) = { + for (i <- Array.range(0, xss(0).length)) yield + for (xs <- xss) yield xs(i) +} +``` - Here is a function to compute the scalar product of two vectors: +Here is a function to compute the scalar product of two vectors: - ``` - def scalprod(xs: Array[Double], ys: Array[Double]) = { - var acc = 0.0 - for ((x, y) <- xs zip ys) acc = acc + x * y - acc - } - ``` +``` +def scalprod(xs: Array[Double], ys: Array[Double]) = { + var acc = 0.0 + for ((x, y) <- xs zip ys) acc = acc + x * y + acc +} +``` - Finally, here is a function to compute the product of two matrices. - Compare with the imperative version of \ref{ex:imp-mat-mul}. +Finally, here is a function to compute the product of two matrices. +Compare with the [imperative version](#example-imperative-matrix-multiplication). - ``` - def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = { - val ysst = transpose(yss) - for (xs <- xss) yield - for (yst <- ysst) yield - scalprod(xs, yst) - } - ``` +``` +def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = { + val ysst = transpose(yss) + for (xs <- xss) yield + for (yst <- ysst) yield + scalprod(xs, yst) +} +``` - The code above makes use of the fact that `map`, `flatMap`, - `withFilter`, and `foreach` are defined for instances of class - `scala.Array`. +The code above makes use of the fact that `map`, `flatMap`, +`withFilter`, and `foreach` are defined for instances of class +`scala.Array`. ## Return Expressions @@ -1231,23 +1242,24 @@ parameter section itself does not count as an implicit parameter section in the sense defined [here](#implicit-parameters). Hence, arguments to anonymous functions always have to be given explicitly. -(@) Examples of anonymous functions: +###### Example +Examples of anonymous functions: - ``` - x => x // The identity function +``` +x => x // The identity function - f => g => x => f(g(x)) // Curried function composition +f => g => x => f(g(x)) // Curried function composition - (x: Int,y: Int) => x + y // A summation function +(x: Int,y: Int) => x + y // A summation function - () => { count += 1; count } // The function which takes an - // empty parameter list $()$, - // increments a non-local variable - // `count' and returns the new value. +() => { count += 1; count } // The function which takes an + // empty parameter list $()$, + // increments a non-local variable + // `count' and returns the new value. - _ => 5 // The function that ignores its argument - // and always returns 5. - ``` +_ => 5 // The function that ignores its argument + // and always returns 5. +``` ### Placeholder Syntax for Anonymous Functions @@ -1276,17 +1288,18 @@ the anonymous function `($u'_1$, ... $u'_n$) => $e'$` where each $u_i'$ results from $u_i$ by replacing the underscore with a fresh identifier and $e'$ results from $e$ by replacing each underscore section $u_i$ by $u_i'$. -(@) The anonymous functions in the left column use placeholder - syntax. Each of these is equivalent to the anonymous function on its right. +###### Example +The anonymous functions in the left column use placeholder +syntax. Each of these is equivalent to the anonymous function on its right. - --------------------------- ------------------------------------ - `_ + 1` `x => x + 1` - `_ * _` `(x1, x2) => x1 * x2` - `(_: Int) * 2` `(x: Int) => (x: Int) * 2` - `if (_) x else y` `z => if (z) x else y` - `_.map(f)` `x => x.map(f)` - `_.map(_ + 1)` `x => x.map(y => y + 1)` - --------------------------- ------------------------------------ +|---------------------------|----------------------------| +|`_ + 1` | `x => x + 1` | +|`_ * _` | `(x1, x2) => x1 * x2` | +|`(_: Int) * 2` | `(x: Int) => (x: Int) * 2` | +|`if (_) x else y` | `z => if (z) x else y` | +|`_.map(f)` | `x => x.map(f)` | +|`_.map(_ + 1)` | `x => x.map(y => y + 1)` | +|---------------------------|----------------------------| ## Constant Expressions @@ -1539,26 +1552,27 @@ alternatives in $\mathscr{B}$. It is an error if there is no alternative in $\mathscr{B}$ which is more specific than all other alternatives in $\mathscr{B}$. -(@) Consider the following definitions: +###### Example +Consider the following definitions: - ``` - class A extends B {} - def f(x: B, y: B) = $\ldots$ - def f(x: A, y: B) = $\ldots$ - val a: A - val b: B - ``` +``` +class A extends B {} +def f(x: B, y: B) = $\ldots$ +def f(x: A, y: B) = $\ldots$ +val a: A +val b: B +``` - Then the application `f(b, b)` refers to the first - definition of $f$ whereas the application `f(a, a)` - refers to the second. Assume now we add a third overloaded definition +Then the application `f(b, b)` refers to the first +definition of $f$ whereas the application `f(a, a)` +refers to the second. Assume now we add a third overloaded definition - ``` - def f(x: B, y: A) = $\ldots$ - ``` +``` +def f(x: B, y: A) = $\ldots$ +``` - Then the application `f(a, a)` is rejected for being ambiguous, since - no most specific applicable signature exists. +Then the application `f(a, a)` is rejected for being ambiguous, since +no most specific applicable signature exists. ### Local Type Inference @@ -1653,95 +1667,98 @@ pre-order, it is also possible that a solution set has several optimal solutions for a type. In that case, a Scala compiler is free to pick any one of them. -(@) Consider the two methods: +###### Example +Consider the two methods: - ``` - def cons[A](x: A, xs: List[A]): List[A] = x :: xs - def nil[B]: List[B] = Nil - ``` +``` +def cons[A](x: A, xs: List[A]): List[A] = x :: xs +def nil[B]: List[B] = Nil +``` - and the definition +and the definition - ``` - val xs = cons(1, nil) - ``` +``` +val xs = cons(1, nil) +``` - The application of `cons` is typed with an undefined expected - type. This application is completed by local type inference to - `cons[Int](1, nil)`. - Here, one uses the following - reasoning to infer the type argument `Int` for the type - parameter `a`: +The application of `cons` is typed with an undefined expected +type. This application is completed by local type inference to +`cons[Int](1, nil)`. +Here, one uses the following +reasoning to infer the type argument `Int` for the type +parameter `a`: - First, the argument expressions are typed. The first argument `1` - has type `Int` whereas the second argument `nil` is - itself polymorphic. One tries to type-check `nil` with an - expected type `List[a]`. This leads to the constraint system +First, the argument expressions are typed. The first argument `1` +has type `Int` whereas the second argument `nil` is +itself polymorphic. One tries to type-check `nil` with an +expected type `List[a]`. This leads to the constraint system - ``` - List[b?] <: List[a] - ``` +``` +List[b?] <: List[a] +``` - where we have labeled `b?` with a question mark to indicate - that it is a variable in the constraint system. - Because class `List` is covariant, the optimal - solution of this constraint is +where we have labeled `b?` with a question mark to indicate +that it is a variable in the constraint system. +Because class `List` is covariant, the optimal +solution of this constraint is - ``` - b = scala.Nothing - ``` +``` +b = scala.Nothing +``` - In a second step, one solves the following constraint system for - the type parameter `a` of `cons`: +In a second step, one solves the following constraint system for +the type parameter `a` of `cons`: - ``` - Int <: a? - List[scala.Nothing] <: List[a?] - List[a?] <: $\mbox{\sl undefined}$ - ``` +``` +Int <: a? +List[scala.Nothing] <: List[a?] +List[a?] <: $\mbox{\sl undefined}$ +``` - The optimal solution of this constraint system is +The optimal solution of this constraint system is - ``` - a = Int - ``` +``` +a = Int +``` - so `Int` is the type inferred for `a`. +so `Int` is the type inferred for `a`. -(@) Consider now the definition +###### Example - ``` - val ys = cons("abc", xs) - ``` +Consider now the definition - where `xs` is defined of type `List[Int]` as before. - In this case local type inference proceeds as follows. +``` +val ys = cons("abc", xs) +``` - First, the argument expressions are typed. The first argument - `"abc"` has type `String`. The second argument `xs` is - first tried to be typed with expected type `List[a]`. This fails, - as `List[Int]` is not a subtype of `List[a]`. Therefore, - the second strategy is tried; `xs` is now typed with expected type - `List[$\mbox{\sl undefined}$]`. This succeeds and yields the argument type - `List[Int]`. +where `xs` is defined of type `List[Int]` as before. +In this case local type inference proceeds as follows. - In a second step, one solves the following constraint system for - the type parameter `a` of `cons`: +First, the argument expressions are typed. The first argument +`"abc"` has type `String`. The second argument `xs` is +first tried to be typed with expected type `List[a]`. This fails, +as `List[Int]` is not a subtype of `List[a]`. Therefore, +the second strategy is tried; `xs` is now typed with expected type +`List[$\mbox{\sl undefined}$]`. This succeeds and yields the argument type +`List[Int]`. - ``` - String <: a? - List[Int] <: List[a?] - List[a?] <: $\mbox{\sl undefined}$ - ``` +In a second step, one solves the following constraint system for +the type parameter `a` of `cons`: - The optimal solution of this constraint system is +``` +String <: a? +List[Int] <: List[a?] +List[a?] <: $\mbox{\sl undefined}$ +``` - ``` - a = scala.Any - ``` +The optimal solution of this constraint system is + +``` +a = scala.Any +``` - so `scala.Any` is the type inferred for `a`. +so `scala.Any` is the type inferred for `a`. ### Eta Expansion diff --git a/09-implicit-parameters-and-views.md b/09-implicit-parameters-and-views.md index 845d21e579..e4b8b5956c 100644 --- a/09-implicit-parameters-and-views.md +++ b/09-implicit-parameters-and-views.md @@ -13,26 +13,27 @@ and can be used as implicit conversions called [views](#views). The `implicit` modifier is illegal for all type members, as well as for [top-level objects](#packagings). -(@impl-monoid) The following code defines an abstract class of monoids and - two concrete implementations, `StringMonoid` and - `IntMonoid`. The two implementations are marked implicit. - - ``` - abstract class Monoid[A] extends SemiGroup[A] { - def unit: A - def add(x: A, y: A): A - } - object Monoids { - implicit object stringMonoid extends Monoid[String] { - def add(x: String, y: String): String = x.concat(y) - def unit: String = "" - } - implicit object intMonoid extends Monoid[Int] { - def add(x: Int, y: Int): Int = x + y - def unit: Int = 0 - } - } - ``` +###### Example: `Monoid` +The following code defines an abstract class of monoids and +two concrete implementations, `StringMonoid` and +`IntMonoid`. The two implementations are marked implicit. + +``` +abstract class Monoid[A] extends SemiGroup[A] { + def unit: A + def add(x: A, y: A): A +} +object Monoids { + implicit object stringMonoid extends Monoid[String] { + def add(x: String, y: String): String = x.concat(y) + def unit: String = "" + } + implicit object intMonoid extends Monoid[Int] { + def add(x: Int, y: Int): Int = x + y + def unit: Int = 0 + } +} +``` ## Implicit Parameters @@ -85,25 +86,26 @@ of static [overloading resolution](#overloading-resolution). If the parameter has a default argument and no implicit argument can be found the default argument is used. -(@) Assuming the classes from \ref{ex:impl-monoid}, here is a - method which computes the sum of a list of elements using the - monoid's `add` and `unit` operations. +###### Example +Assuming the classes from the [`Monoid` example](#example-monoid), here is a +method which computes the sum of a list of elements using the +monoid's `add` and `unit` operations. - ``` - def sum[A](xs: List[A])(implicit m: Monoid[A]): A = - if (xs.isEmpty) m.unit - else m.add(xs.head, sum(xs.tail)) - ``` +``` +def sum[A](xs: List[A])(implicit m: Monoid[A]): A = + if (xs.isEmpty) m.unit + else m.add(xs.head, sum(xs.tail)) +``` - The monoid in question is marked as an implicit parameter, and can therefore - be inferred based on the type of the list. - Consider for instance the call `sum(List(1, 2, 3))` - in a context where `stringMonoid` and `intMonoid` - are visible. We know that the formal type parameter `a` of - `sum` needs to be instantiated to `Int`. The only - eligible object which matches the implicit formal parameter type - `Monoid[Int]` is `intMonoid` so this object will - be passed as implicit parameter. +The monoid in question is marked as an implicit parameter, and can therefore +be inferred based on the type of the list. +Consider for instance the call `sum(List(1, 2, 3))` +in a context where `stringMonoid` and `intMonoid` +are visible. We know that the formal type parameter `a` of +`sum` needs to be instantiated to `Int`. The only +eligible object which matches the implicit formal parameter type +`Monoid[Int]` is `intMonoid` so this object will +be passed as implicit parameter. This discussion also shows that implicit parameters are inferred after @@ -210,39 +212,41 @@ the type: > `$\mathit{complexity}(T_1$ with $\ldots$ with $T_n)$` $= \Sigma\mathit{complexity}(T_i)$ -(@) When typing `sort(xs)` for some list `xs` of type `List[List[List[Int]]]`, - the sequence of types for - which implicit arguments are searched is +###### Example +When typing `sort(xs)` for some list `xs` of type `List[List[List[Int]]]`, +the sequence of types for +which implicit arguments are searched is - ``` - List[List[Int]] => Ordered[List[List[Int]]], - List[Int] => Ordered[List[Int]] - Int => Ordered[Int] - ``` +``` +List[List[Int]] => Ordered[List[List[Int]]], +List[Int] => Ordered[List[Int]] +Int => Ordered[Int] +``` - All types share the common type constructor `scala.Function1`, - but the complexity of the each new type is lower than the complexity of the previous types. - Hence, the code typechecks. +All types share the common type constructor `scala.Function1`, +but the complexity of the each new type is lower than the complexity of the previous types. +Hence, the code typechecks. -(@) Let `ys` be a list of some type which cannot be converted - to `Ordered`. For instance: +###### Example +Let `ys` be a list of some type which cannot be converted +to `Ordered`. For instance: - ``` - val ys = List(new IllegalArgumentException, new ClassCastException, new Error) - ``` +``` +val ys = List(new IllegalArgumentException, new ClassCastException, new Error) +``` - Assume that the definition of `magic` above is in scope. Then the sequence - of types for which implicit arguments are searched is +Assume that the definition of `magic` above is in scope. Then the sequence +of types for which implicit arguments are searched is - ``` - Throwable => Ordered[Throwable], - Throwable => Ordered[Throwable], - ... - ``` +``` +Throwable => Ordered[Throwable], +Throwable => Ordered[Throwable], +... +``` - Since the second type in the sequence is equal to the first, the compiler - will issue an error signalling a divergent implicit expansion. +Since the second type in the sequence is equal to the first, the compiler +will issue an error signalling a divergent implicit expansion. ## Views @@ -286,33 +290,34 @@ As for implicit parameters, overloading resolution is applied if there are several possible candidates (of either the call-by-value or the call-by-name category). -(@impl-ordered) Class `scala.Ordered[A]` contains a method +###### Example: `Ordered` +Class `scala.Ordered[A]` contains a method - ``` - def <= [B >: A](that: B)(implicit b2ordered: B => Ordered[B]): Boolean . - ``` +``` + def <= [B >: A](that: B)(implicit b2ordered: B => Ordered[B]): Boolean . +``` - Assume two lists `xs` and `ys` of type `List[Int]` - and assume that the `list2ordered` and `int2ordered` - methods defined [here](#implicit-parameters) are in scope. - Then the operation +Assume two lists `xs` and `ys` of type `List[Int]` +and assume that the `list2ordered` and `int2ordered` +methods defined [here](#implicit-parameters) are in scope. +Then the operation - ``` - xs <= ys - ``` +``` + xs <= ys +``` - is legal, and is expanded to: +is legal, and is expanded to: - ``` - list2ordered(xs)(int2ordered).<= - (ys) - (xs => list2ordered(xs)(int2ordered)) - ``` +``` + list2ordered(xs)(int2ordered).<= + (ys) + (xs => list2ordered(xs)(int2ordered)) +``` - The first application of `list2ordered` converts the list - `xs` to an instance of class `Ordered`, whereas the second - occurrence is part of an implicit parameter passed to the `<=` - method. +The first application of `list2ordered` converts the list +`xs` to an instance of class `Ordered`, whereas the second +occurrence is part of an implicit parameter passed to the `<=` +method. ## Context Bounds and View Bounds @@ -360,12 +365,13 @@ Consequently, type-parameters in traits may not be view- or context-bounded. Also, a method or class with view- or context bounds may not define any additional implicit parameters. -(@) The `<=` method mentioned in \ref{ex:impl-ordered} can be declared - more concisely as follows: +###### Example +The `<=` method from the [`Ordered` example](#example-ordered) can be declared +more concisely as follows: - ``` - def <= [B >: A <% Ordered[B]](that: B): Boolean - ``` +``` +def <= [B >: A <% Ordered[B]](that: B): Boolean +``` ## Manifests diff --git a/10-pattern-matching.md b/10-pattern-matching.md index 2d1c79e538..fd63d3fbc9 100644 --- a/10-pattern-matching.md +++ b/10-pattern-matching.md @@ -29,8 +29,8 @@ variables in the pattern to the corresponding components of the value (or sequence of values). The same variable name may not be bound more than once in a pattern. -(@) Some examples of patterns are: - +###### Example +Some examples of patterns are: 1. The pattern `ex: IOException` matches all instances of class `IOException`, binding variable \verb@ex@ to the instance. 1. The pattern `Some(x)` matches values of the form `Some($v$)`, @@ -43,9 +43,9 @@ than once in a pattern. second element, and `xs` to the remainder. 1. The pattern `1 | 2 | 3` matches the integers between 1 and 3. - Pattern matching is always done in a context which supplies an - expected type of the pattern. We distinguish the following kinds of - patterns. +Pattern matching is always done in a context which supplies an +expected type of the pattern. We distinguish the following kinds of +patterns. ### Variable Patterns @@ -113,32 +113,33 @@ stable identifier pattern may not be a simple name starting with a lower-case letter. However, it is possible to enclose a such a variable name in backquotes; then it is treated as a stable identifier pattern. -(@) Consider the following function definition: +###### Example +Consider the following function definition: - ``` - def f(x: Int, y: Int) = x match { - case y => ... - } - ``` +``` +def f(x: Int, y: Int) = x match { + case y => ... +} +``` - Here, `y` is a variable pattern, which matches any value. - If we wanted to turn the pattern into a stable identifier pattern, this - can be achieved as follows: +Here, `y` is a variable pattern, which matches any value. +If we wanted to turn the pattern into a stable identifier pattern, this +can be achieved as follows: - ``` - def f(x: Int, y: Int) = x match { - case `y` => ... - } - ``` +``` +def f(x: Int, y: Int) = x match { + case `y` => ... +} +``` - Now, the pattern matches the `y` parameter of the enclosing function `f`. - That is, the match succeeds only if the `x` argument and the `y` - argument of `f` are equal. +Now, the pattern matches the `y` parameter of the enclosing function `f`. +That is, the match succeeds only if the `x` argument and the `y` +argument of `f` are equal. ### Constructor Patterns ``` - SimplePattern ::= StableId `(' [Patterns] `) +SimplePattern ::= StableId `(' [Patterns] `) ``` A constructor pattern is of the form $c(p_1 , \ldots , p_n)$ where $n @@ -211,31 +212,32 @@ result type is of the form `Option[$S$]`, where $S$ is a subtype of `Seq[$T$]` for some element type $T$. This case is further discussed [here](#pattern-seqs). -(@) The `Predef` object contains a definition of an - extractor object `Pair`: +###### Example +The `Predef` object contains a definition of an +extractor object `Pair`: - ``` - object Pair { - def apply[A, B](x: A, y: B) = Tuple2(x, y) - def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x) - } - ``` +``` +object Pair { + def apply[A, B](x: A, y: B) = Tuple2(x, y) + def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x) +} +``` - This means that the name `Pair` can be used in place of `Tuple2` for tuple - formation as well as for deconstruction of tuples in patterns. - Hence, the following is possible: +This means that the name `Pair` can be used in place of `Tuple2` for tuple +formation as well as for deconstruction of tuples in patterns. +Hence, the following is possible: - ``` - val x = (1, 2) - val y = x match { - case Pair(i, s) => Pair(s + i, i * i) - } - ``` +``` +val x = (1, 2) +val y = x match { + case Pair(i, s) => Pair(s + i, i * i) +} +``` ### Pattern Sequences ``` - SimplePattern ::= StableId `(' [Patterns `,'] [varid `@'] `_' `*' `)' +SimplePattern ::= StableId `(' [Patterns `,'] [varid `@'] `_' `*' `)' ``` A pattern sequence $p_1 , \ldots , p_n$ appears in two @@ -451,76 +453,79 @@ has type type parameters $a_1 , \ldots , a_n$. These type parameters are inferred in the same way as for the typed pattern `(_: $C[a_1 , \ldots , a_n]$)`. -(@) Consider the program fragment: - - ``` - val x: Any - x match { - case y: List[a] => ... - } - ``` - - Here, the type pattern `List[a]` is matched against the - expected type `Any`. The pattern binds the type variable - `a`. Since `List[a]` conforms to `Any` - for every type argument, there are no constraints on `a`. - Hence, `a` is introduced as an abstract type with no - bounds. The scope of `a` is right-hand side of its case clause. - - On the other hand, if `x` is declared as - - ``` - val x: List[List[String]], - ``` - - this generates the constraint - `List[a] <: List[List[String]]`, which simplifies to - `a <: List[String]`, because `List` is covariant. Hence, - `a` is introduced with upper bound - `List[String]`. - -(@) Consider the program fragment: - - ``` - val x: Any - x match { - case y: List[String] => ... - } - ``` - - Scala does not maintain information about type arguments at run-time, - so there is no way to check that `x` is a list of strings. - Instead, the Scala compiler will [erase](#type-erasure) the - pattern to `List[_]`; that is, it will only test whether the - top-level runtime-class of the value `x` conforms to - `List`, and the pattern match will succeed if it does. This - might lead to a class cast exception later on, in the case where the - list `x` contains elements other than strings. The Scala - compiler will flag this potential loss of type-safety with an - ``unchecked'' warning message. - - -(@) Consider the program fragment - - ``` - class Term[A] - class Number(val n: Int) extends Term[Int] - def f[B](t: Term[B]): B = t match { - case y: Number => y.n - } - ``` - - The expected type of the pattern `y: Number` is - `Term[B]`. The type `Number` does not conform to - `Term[B]`; hence Case 2 of the rules above - applies. This means that `b` is treated as another type - variable for which subtype constraints are inferred. In our case the - applicable constraint is `Number <: Term[B]`, which - entails `B = Int`. Hence, `B` is treated in - the case clause as an abstract type with lower and upper bound - `Int`. Therefore, the right hand side of the case clause, - `y.n`, of type `Int`, is found to conform to the - function's declared result type, `Number`. +###### Example +Consider the program fragment: + +``` +val x: Any +x match { + case y: List[a] => ... +} +``` + +Here, the type pattern `List[a]` is matched against the +expected type `Any`. The pattern binds the type variable +`a`. Since `List[a]` conforms to `Any` +for every type argument, there are no constraints on `a`. +Hence, `a` is introduced as an abstract type with no +bounds. The scope of `a` is right-hand side of its case clause. + +On the other hand, if `x` is declared as + +``` +val x: List[List[String]], +``` + +this generates the constraint +`List[a] <: List[List[String]]`, which simplifies to +`a <: List[String]`, because `List` is covariant. Hence, +`a` is introduced with upper bound +`List[String]`. + +###### Example +Consider the program fragment: + +``` +val x: Any +x match { + case y: List[String] => ... +} +``` + +Scala does not maintain information about type arguments at run-time, +so there is no way to check that `x` is a list of strings. +Instead, the Scala compiler will [erase](#type-erasure) the +pattern to `List[_]`; that is, it will only test whether the +top-level runtime-class of the value `x` conforms to +`List`, and the pattern match will succeed if it does. This +might lead to a class cast exception later on, in the case where the +list `x` contains elements other than strings. The Scala +compiler will flag this potential loss of type-safety with an +``unchecked'' warning message. + + +###### Example +Consider the program fragment + +``` +class Term[A] +class Number(val n: Int) extends Term[Int] +def f[B](t: Term[B]): B = t match { + case y: Number => y.n +} +``` + +The expected type of the pattern `y: Number` is +`Term[B]`. The type `Number` does not conform to +`Term[B]`; hence Case 2 of the rules above +applies. This means that `b` is treated as another type +variable for which subtype constraints are inferred. In our case the +applicable constraint is `Number <: Term[B]`, which +entails `B = Int`. Hence, `B` is treated in +the case clause as an abstract type with lower and upper bound +`Int`. Therefore, the right hand side of the case clause, +`y.n`, of type `Int`, is found to conform to the +function's declared result type, `Number`. ## Pattern Matching Expressions @@ -601,43 +606,45 @@ the compilation of pattern matching can emit warnings which diagnose that a given set of patterns is not exhaustive, i.e.\ that there is a possibility of a `MatchError` being raised at run-time. -(@eval) Consider the following definitions of arithmetic terms: - - ``` - abstract class Term[T] - case class Lit(x: Int) extends Term[Int] - case class Succ(t: Term[Int]) extends Term[Int] - case class IsZero(t: Term[Int]) extends Term[Boolean] - case class If[T](c: Term[Boolean], - t1: Term[T], - t2: Term[T]) extends Term[T] - ``` - - There are terms to represent numeric literals, incrementation, a zero - test, and a conditional. Every term carries as a type parameter the - type of the expression it representes (either `Int` or `Boolean`). - - A type-safe evaluator for such terms can be written as follows. - - ``` - def eval[T](t: Term[T]): T = t match { - case Lit(n) => n - case Succ(u) => eval(u) + 1 - case IsZero(u) => eval(u) == 0 - case If(c, u1, u2) => eval(if (eval(c)) u1 else u2) - } - ``` - - Note that the evaluator makes crucial use of the fact that type - parameters of enclosing methods can acquire new bounds through pattern - matching. - - For instance, the type of the pattern in the second case, - `Succ(u)`, is `Int`. It conforms to the selector type - `T` only if we assume an upper and lower bound of `Int` for `T`. - Under the assumption `Int <: T <: Int` we can also - verify that the type right hand side of the second case, `Int` - conforms to its expected type, `T`. +###### Example: `eval` + +Consider the following definitions of arithmetic terms: + +``` +abstract class Term[T] +case class Lit(x: Int) extends Term[Int] +case class Succ(t: Term[Int]) extends Term[Int] +case class IsZero(t: Term[Int]) extends Term[Boolean] +case class If[T](c: Term[Boolean], + t1: Term[T], + t2: Term[T]) extends Term[T] +``` + +There are terms to represent numeric literals, incrementation, a zero +test, and a conditional. Every term carries as a type parameter the +type of the expression it representes (either `Int` or `Boolean`). + +A type-safe evaluator for such terms can be written as follows. + +``` +def eval[T](t: Term[T]): T = t match { + case Lit(n) => n + case Succ(u) => eval(u) + 1 + case IsZero(u) => eval(u) == 0 + case If(c, u1, u2) => eval(if (eval(c)) u1 else u2) +} +``` + +Note that the evaluator makes crucial use of the fact that type +parameters of enclosing methods can acquire new bounds through pattern +matching. + +For instance, the type of the pattern in the second case, +`Succ(u)`, is `Int`. It conforms to the selector type +`T` only if we assume an upper and lower bound of `Int` for `T`. +Under the assumption `Int <: T <: Int` we can also +verify that the type right hand side of the second case, `Int` +conforms to its expected type, `T`. ## Pattern Matching Anonymous Functions @@ -701,23 +708,24 @@ types of all $b_i$. The final default case in the `isDefinedAt` method is omitted if one of the patterns $p_1 , \ldots , p_n$ is already a variable or wildcard pattern. -(@) Here is a method which uses a fold-left operation - `/:` to compute the scalar product of - two vectors: - - ``` - def scalarProduct(xs: Array[Double], ys: Array[Double]) = - (0.0 /: (xs zip ys)) { - case (a, (b, c)) => a + b * c - } - ``` - - The case clauses in this code are equivalent to the following - anonymous function: - - ``` - (x, y) => (x, y) match { - case (a, (b, c)) => a + b * c - } - ``` +###### Example +Here is a method which uses a fold-left operation +`/:` to compute the scalar product of +two vectors: + +``` +def scalarProduct(xs: Array[Double], ys: Array[Double]) = + (0.0 /: (xs zip ys)) { + case (a, (b, c)) => a + b * c + } +``` + +The case clauses in this code are equivalent to the following +anonymous function: + +``` +(x, y) => (x, y) match { + case (a, (b, c)) => a + b * c +} +``` diff --git a/11-top-level-definitions.md b/11-top-level-definitions.md index e7d6a9c192..dc25e7e476 100644 --- a/11-top-level-definitions.md +++ b/11-top-level-definitions.md @@ -119,25 +119,26 @@ closest enclosing scope that defines a member named $p$. The special predefined name `_root_` refers to the outermost root package which contains all top-level packages. -(@package-ids) Consider the following program: +###### Example +Consider the following program: - ``` - package b { - class B - } +``` +package b { + class B +} - package a.b { - class A { - val x = new _root_.b.B - } - } - ``` +package a.b { + class A { + val x = new _root_.b.B + } +} +``` - Here, the reference `_root_.b.B` refers to class `B` in the - toplevel package `b`. If the `_root_` prefix had been - omitted, the name `b` would instead resolve to the package - `a.b`, and, provided that package does not also - contain a class `B`, a compiler-time error would result. +Here, the reference `_root_.b.B` refers to class `B` in the +toplevel package `b`. If the `_root_` prefix had been +omitted, the name `b` would instead resolve to the package +`a.b`, and, provided that package does not also +contain a class `B`, a compiler-time error would result. ## Programs @@ -154,37 +155,38 @@ object, or it can be inherited. The scala library defines a special class An objects $m$ inheriting from this class is thus a program, which executes the initializaton code of the object $m$. -(@) The following example will create a hello world program by defining - a method `main` in module `test.HelloWorld`. +###### Example +The following example will create a hello world program by defining +a method `main` in module `test.HelloWorld`. - ``` - package test - object HelloWorld { - def main(args: Array[String]) { println("Hello World") } - } - ``` +``` +package test +object HelloWorld { + def main(args: Array[String]) { println("Hello World") } +} +``` - This program can be started by the command +This program can be started by the command - ``` - scala test.HelloWorld - ``` +``` +scala test.HelloWorld +``` - In a Java environment, the command +In a Java environment, the command - ``` - java test.HelloWorld - ``` +``` +java test.HelloWorld +``` - would work as well. +would work as well. - `HelloWorld` can also be defined without a `main` method - by inheriting from `App` instead: +`HelloWorld` can also be defined without a `main` method +by inheriting from `App` instead: - ``` - package test - object HelloWorld extends App { - println("Hello World") - } - ``` +``` +package test +object HelloWorld extends App { + println("Hello World") +} +``` diff --git a/12-xml-expressions-and-patterns.md b/12-xml-expressions-and-patterns.md index 974fbc6b78..b6998da116 100644 --- a/12-xml-expressions-and-patterns.md +++ b/12-xml-expressions-and-patterns.md @@ -1,6 +1,6 @@ # XML Expressions and Patterns -__By Burak Emir__ \ +__By Burak Emir__ This chapter describes the syntactic structure of XML expressions and patterns. It follows as closely as possible the XML 1.0 specification \cite{w3c:xml}, @@ -44,7 +44,7 @@ XmlContent ::= Element | CDSect | PI | Comment -``` +``` If an XML expression is a single element, its value is a runtime representation of an XML node (an instance of a subclass of @@ -95,7 +95,6 @@ Name ::= XNameStart {NameChar} XNameStart ::= ‘_’ | BaseChar | Ideographic $\mbox{\rm\em (as in W3C XML, but without }$ ‘:’ - ``` ## XML patterns diff --git a/14-the-scala-standard-library.md b/14-the-scala-standard-library.md index 59927f4e98..3bfeb9013c 100644 --- a/14-the-scala-standard-library.md +++ b/14-the-scala-standard-library.md @@ -234,53 +234,55 @@ for type `Int` and for all subrange types. The `toString` method displays its receiver as an integer or floating point number. -(@) As an example, here is the signature of the numeric value type `Int`: +###### Example: - ``` - package scala - abstract sealed class Int extends AnyVal { - def == (that: Double): Boolean // double equality - def == (that: Float): Boolean // float equality - def == (that: Long): Boolean // long equality - def == (that: Int): Boolean // int equality - def == (that: Short): Boolean // int equality - def == (that: Byte): Boolean // int equality - def == (that: Char): Boolean // int equality - /* analogous for !=, <, >, <=, >= */ - - def + (that: Double): Double // double addition - def + (that: Float): Double // float addition - def + (that: Long): Long // long addition - def + (that: Int): Int // int addition - def + (that: Short): Int // int addition - def + (that: Byte): Int // int addition - def + (that: Char): Int // int addition - /* analogous for -, *, /, % */ - - def & (that: Long): Long // long bitwise and - def & (that: Int): Int // int bitwise and - def & (that: Short): Int // int bitwise and - def & (that: Byte): Int // int bitwise and - def & (that: Char): Int // int bitwise and - /* analogous for |, ^ */ - - def << (cnt: Int): Int // int left shift - def << (cnt: Long): Int // long left shift - /* analogous for >>, >>> */ - - def unary_+ : Int // int identity - def unary_- : Int // int negation - def unary_~ : Int // int bitwise negation - - def toByte: Byte // convert to Byte - def toShort: Short // convert to Short - def toChar: Char // convert to Char - def toInt: Int // convert to Int - def toLong: Long // convert to Long - def toFloat: Float // convert to Float - def toDouble: Double // convert to Double - } - ``` +This is the signature of the numeric value type `Int`: + +``` +package scala +abstract sealed class Int extends AnyVal { + def == (that: Double): Boolean // double equality + def == (that: Float): Boolean // float equality + def == (that: Long): Boolean // long equality + def == (that: Int): Boolean // int equality + def == (that: Short): Boolean // int equality + def == (that: Byte): Boolean // int equality + def == (that: Char): Boolean // int equality + /* analogous for !=, <, >, <=, >= */ + + def + (that: Double): Double // double addition + def + (that: Float): Double // float addition + def + (that: Long): Long // long addition + def + (that: Int): Int // int addition + def + (that: Short): Int // int addition + def + (that: Byte): Int // int addition + def + (that: Char): Int // int addition + /* analogous for -, *, /, % */ + + def & (that: Long): Long // long bitwise and + def & (that: Int): Int // int bitwise and + def & (that: Short): Int // int bitwise and + def & (that: Byte): Int // int bitwise and + def & (that: Char): Int // int bitwise and + /* analogous for |, ^ */ + + def << (cnt: Int): Int // int left shift + def << (cnt: Long): Int // long left shift + /* analogous for >>, >>> */ + + def unary_+ : Int // int identity + def unary_- : Int // int negation + def unary_~ : Int // int bitwise negation + + def toByte: Byte // convert to Byte + def toShort: Short // convert to Short + def toChar: Char // convert to Char + def toInt: Int // convert to Int + def toLong: Long // convert to Long + def toFloat: Float // convert to Float + def toDouble: Double // convert to Double +} +``` ### Class `Boolean` @@ -427,12 +429,12 @@ Because of the syntactic sugar for `apply` and `update` operations, we have the following correspondences between Scala and Java/C# code for operations on an array `xs`: ------------------- ---------------------- -_Scala_ _Java/C#_ -`xs.length` `xs.length` -`xs(i)` `xs[i]` -`xs(i) = e` `xs[i] = e` ------------------- ---------------------- +|------------------|------------| +|_Scala_ |_Java/C#_ | +|`xs.length` |`xs.length` | +|`xs(i)` |`xs[i]` | +|`xs(i) = e` |`xs[i] = e` | +|------------------|------------| Two implicit conversions exist in `Predef` that are frequently applied to arrays: a conversion to `scala.collection.mutable.ArrayOps` and a conversion to @@ -495,11 +497,9 @@ def mkArray[T : ClassTag](elems: Seq[T]): Array[T] = { If type $T$ is a type for which the host platform offers a specialized array representation, this representation is used. -(@) On the Java Virtual Machine, an invocation of - ``` - mkArray(List(1,2,3)) - ``` - will return a primitive array of `int`s, written as `int[]` in Java. +###### Example +On the Java Virtual Machine, an invocation of `mkArray(List(1,2,3))` +will return a primitive array of `int`s, written as `int[]` in Java. #### Companion object |