From 71c1716ae4f16a05825695a33d480ac194c5ae09 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 26 Mar 2014 21:40:02 -0700 Subject: Add language to code blocks. Shorter Example title. --- 08-expressions.md | 146 +++++++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 73 deletions(-) (limited to '08-expressions.md') diff --git a/08-expressions.md b/08-expressions.md index 1c72e4734e..db1bd182cd 100644 --- a/08-expressions.md +++ b/08-expressions.md @@ -6,7 +6,7 @@ chapter: 6 # Expressions -``` +```ebnf Expr ::= (Bindings | id | `_') `=>' Expr | Expr1 Expr1 ::= `if' `(' Expr `)' {nl} Expr [[semi] `else' Expr] @@ -66,14 +66,14 @@ type $T$ and let $t_1[\mathit{tps}_1] >: L_1 <: U_1 , \ldots , t_n[\mathit{tps}_ all the type variables created by skolemization of some part of $e$ which are free in $T$. Then the _packed type_ of $e$ is -``` +```scala $T$ forSome { type $t_1[\mathit{tps}_1] >: L_1 <: U_1$; $\ldots$; type $t_n[\mathit{tps}_n] >: L_n <: U_n$ }. ``` ## Literals -``` +```ebnf SimpleExpr ::= Literal ``` @@ -102,7 +102,7 @@ A reference to any other member of the "null" object causes a ## Designators -``` +```ebnf SimpleExpr ::= Path | SimpleExpr `.' id ``` @@ -160,7 +160,7 @@ is thrown. ## This and Super -``` +```ebnf SimpleExpr ::= [id `.'] `this' | [id '.'] `super' [ClassQualifier] `.' id ``` @@ -210,10 +210,10 @@ 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. -### Example: +### Example Consider the following class definitions -``` +```scala 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 } @@ -229,7 +229,7 @@ The linearization of class `C` is `{C, B, Root}` and the linearization of class `D` is `{D, B, A, Root}`. Then we have: -``` +```scala (new A).superA == "Root", (new C).superB = "Root", (new C).superC = "B", (new D).superA == "Root", (new D).superB = "A", (new D).superD = "B", @@ -241,7 +241,7 @@ depending on whether `B` is mixed in with class `Root` or `A`. ## Function Applications -``` +```ebnf SimpleExpr ::= SimpleExpr1 ArgumentExprs ArgumentExprs ::= `(' [Exprs] `)' | `(' [Exprs `,'] PostfixExpr `:' `_' `*' ')' @@ -326,20 +326,20 @@ of the caller. Assume the following function which computes the sum of a variable number of arguments: -``` +```scala def sum(xs: Int*) = (0 /: xs) ((x, y) => x + y) ``` Then -``` +```scala sum(1, 2, 3, 4) sum(List(1, 2, 3, 4): _*) ``` both yield `10` as result. On the other hand, -``` +```scala sum(List(1, 2, 3, 4)) ``` @@ -369,7 +369,7 @@ If the function $f$ has the form `$p.m$[$\mathit{targs}$]` it is transformed into the block -``` +```scala { val q = $p$ q.$m$[$\mathit{targs}$] } @@ -379,7 +379,7 @@ If the function $f$ is itself an application expression the transformation is applied recursively on $f$. The result of transforming $f$ is a block of the form -``` +```scala { val q = $p$ val $x_1$ = expr$_1$ $\ldots$ @@ -404,7 +404,7 @@ that the position of each name matches the position of its corresponding parameter in the method type `($p_1:T_1 , \ldots , p_n:T_n$)$U$`. The final result of the transformation is a block of the form -``` +```scala { val q = $p$ val $x_1$ = expr$_1$ $\ldots$ @@ -422,7 +422,7 @@ The final result of the transformation is a block of the form ## Method Values -``` +```ebnf SimpleExpr ::= SimpleExpr1 `_' ``` @@ -455,7 +455,7 @@ because otherwise the underscore would be considered part of the name. ## Type Applications -``` +```ebnf SimpleExpr ::= SimpleExpr TypeArgs ``` @@ -482,7 +482,7 @@ and the expected result type. ## Tuples -``` +```ebnf SimpleExpr ::= `(' [Exprs] `)' ``` @@ -495,7 +495,7 @@ The empty tuple ## Instance Creation Expressions -``` +```ebnf SimpleExpr ::= `new' (ClassTemplate | TemplateBody) ``` @@ -510,7 +510,7 @@ $T$. The concrete self type is normally $T$, except if the expression `new $c$` appears as the right hand side of a value definition -``` +```scala val $x$: $S$ = new $c$ ``` @@ -526,7 +526,7 @@ A general instance creation expression is of the form `new $t$` for some [class template](07-classes-and-objects.html#templates) $t$. Such an expression is equivalent to the block -``` +```scala { class $a$ extends $t$; new $a$ } ``` @@ -541,19 +541,19 @@ types: If `{$D$}` is a class body, then ###### Example Consider the following structural instance creation expression: -``` +```scala new { def getName() = "aaron" } ``` This is a shorthand for the general instance creation expression -``` +```scala new AnyRef{ def getName() = "aaron" } ``` The latter is in turn a shorthand for the block -``` +```scala { class anon\$X extends AnyRef{ def getName() = "aaron" }; new anon\$X } ``` @@ -562,7 +562,7 @@ where `anon\$X` is some freshly created name. ## Blocks -``` +```ebnf BlockExpr ::= ‘{’ CaseClauses ‘}’ | ‘{’ Block ‘}’ Block ::= BlockStat {semi BlockStat} [ResultExpr] @@ -609,14 +609,14 @@ $e$, which defines the result of the block. ###### Example Assuming a class `Ref[T](x: T)`, the block -``` +```scala { class C extends B {$\ldots$} ; new Ref(new C) } ``` has the type `Ref[_1] forSome { type _1 <: B }`. The block -``` +```scala { class C extends B {$\ldots$} ; new C } ``` @@ -627,7 +627,7 @@ the existentially quantified type ## Prefix, Infix, and Postfix Operations -``` +```ebnf PostfixExpr ::= InfixExpr [id [nl]] InfixExpr ::= PrefixExpr | InfixExpr id [nl] InfixExpr @@ -668,7 +668,7 @@ The _precedence_ of an infix operator is determined by the operator's first character. Characters are listed below in increasing order of precedence, with characters on the same line having the same precedence. -``` +```scala (all letters) | ^ @@ -742,7 +742,7 @@ operation `$l$ += $r$`, where $l$, $r$ are expressions. This operation can be re-interpreted as an operation which corresponds to the assignment -``` +```scala $l$ = $l$ + $r$ ``` @@ -762,7 +762,7 @@ The re-interpretation occurs if the following two conditions are fulfilled. ## Typed Expressions -``` +```ebnf Expr1 ::= PostfixExpr `:' CompoundType ``` @@ -773,7 +773,7 @@ the expression is the value of $e$ converted to type $T$. ###### Example Here are examples of well-typed and ill-typed expressions. -``` +```scala 1: Int // legal, of type Int 1: Long // legal, of type Long // 1: string // ***** illegal @@ -782,7 +782,7 @@ Here are examples of well-typed and ill-typed expressions. ## Annotated Expressions -``` +```ebnf Expr1 ::= PostfixExpr `:' Annotation {Annotation} ``` @@ -793,7 +793,7 @@ expression $e$. ## Assignments -``` +```ebnf Expr1 ::= [SimpleExpr `.'] id `=' Expr | SimpleExpr1 ArgumentExprs `=' Expr ``` @@ -825,11 +825,11 @@ Here are some assignment expressions and their equivalent expansions. `x.f(i, j) = e` x.f.update(i, j, e) -------------------------- --------------------- -### Example: +### Example Here is the usual imperative code for matrix multiplication. -``` +```scala 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 @@ -854,7 +854,7 @@ def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = { Desugaring the array accesses and assignments yields the following expanded version: -``` +```scala 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 @@ -879,7 +879,7 @@ def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = { ## Conditional Expressions -``` +```ebnf Expr1 ::= `if' `(' Expr `)' {nl} Expr [[semi] `else' Expr] ``` @@ -905,7 +905,7 @@ evaluated as if it was `if ($e_1$) $e_2$ else ()`. ## While Loop Expressions -``` +```ebnf Expr1 ::= `while' `(' Expr ')' {nl} Expr ``` @@ -913,7 +913,7 @@ The while loop expression `while ($e_1$) $e_2$` is typed and evaluated as if it was an application of `whileLoop ($e_1$) ($e_2$)` where the hypothetical function `whileLoop` is defined as follows. -``` +```scala def whileLoop(cond: => Boolean)(body: => Unit): Unit = if (cond) { body ; whileLoop(cond)(body) } else {} ``` @@ -921,7 +921,7 @@ def whileLoop(cond: => Boolean)(body: => Unit): Unit = ## Do Loop Expressions -``` +```ebnf Expr1 ::= `do' Expr [semi] `while' `(' Expr ')' ``` @@ -932,7 +932,7 @@ A semicolon preceding the `while` symbol of a do loop expression is ignored. ## For Comprehensions and For Loops -``` +```ebnf Expr1 ::= `for' (`(' Enumerators `)' | `{' Enumerators `}') {nl} [`yield'] Expr Enumerators ::= Generator {semi Generator} @@ -961,7 +961,7 @@ The translation scheme is as follows. In a first step, every generator `$p$ <- $e$`, where $p$ is not [irrefutable](10-pattern-matching.html#patterns) for the type of $e$ is replaced by -``` +```scala $p$ <- $e$.withFilter { case $p$ => true; case _ => false } ``` @@ -1022,7 +1022,7 @@ comprehensions have been eliminated. The following code produces all pairs of numbers between $1$ and $n-1$ whose sums are prime. -``` +```scala for { i <- 1 until n j <- 1 until i if isPrime(i+j) @@ -1031,7 +1031,7 @@ for { i <- 1 until n The for comprehension is translated to: -``` +```scala (1 until n) .flatMap { case i => (1 until i) @@ -1046,7 +1046,7 @@ For instance, here is a function to compute the transpose of a given matrix: -``` +```scala def transpose[A](xss: Array[Array[A]]) = { for (i <- Array.range(0, xss(0).length)) yield for (xs <- xss) yield xs(i) @@ -1055,7 +1055,7 @@ def transpose[A](xss: Array[Array[A]]) = { Here is a function to compute the scalar product of two vectors: -``` +```scala def scalprod(xs: Array[Double], ys: Array[Double]) = { var acc = 0.0 for ((x, y) <- xs zip ys) acc = acc + x * y @@ -1066,7 +1066,7 @@ def scalprod(xs: Array[Double], ys: Array[Double]) = { Finally, here is a function to compute the product of two matrices. Compare with the [imperative version](#example-imperative-matrix-multiplication). -``` +```scala def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = { val ysst = transpose(yss) for (xs <- xss) yield @@ -1082,7 +1082,7 @@ The code above makes use of the fact that `map`, `flatMap`, ## Return Expressions -``` +```ebnf Expr1 ::= `return' [Expr] ``` @@ -1120,7 +1120,7 @@ and will propagate up the call stack. ## Throw Expressions -``` +```ebnf Expr1 ::= `throw' Expr ``` @@ -1138,7 +1138,7 @@ is `scala.Nothing`. ## Try Expressions -``` +```ebnf Expr1 ::= `try' `{' Block `}' [`catch' `{' CaseClauses `}'] [`finally' Expr] ``` @@ -1147,7 +1147,7 @@ A try expression is of the form `try { $b$ } catch $h$` where the handler $h$ is a [pattern matching anonymous function](#pattern-matching-anonymous-functions) -``` +```scala { case $p_1$ => $b_1$ $\ldots$ case $p_n$ => $b_n$ } ``` @@ -1193,7 +1193,7 @@ for `try { try { $b$ } catch $e_1$ } finally $e_2$`. ## Anonymous Functions -``` +```ebnf Expr ::= (Bindings | [`implicit'] id | `_') `=>' Expr ResultExpr ::= (Bindings | ([`implicit'] id | `_') `:' CompoundType) `=>' Block Bindings ::= `(' Binding {`,' Binding} `)' @@ -1221,7 +1221,7 @@ type which does not refer to any of the formal parameters $x_i$. The anonymous function is evaluated as the instance creation expression -``` +```scala new scala.Function$n$[$T_1 , \ldots , T_n$, $T$] { def apply($x_1$: $T_1 , \ldots , x_n$: $T_n$): $T$ = $e$ } @@ -1247,7 +1247,7 @@ anonymous functions always have to be given explicitly. ###### Example Examples of anonymous functions: -``` +```scala x => x // The identity function f => g => x => f(g(x)) // Curried function composition @@ -1266,7 +1266,7 @@ _ => 5 // The function that ignores its argument ### Placeholder Syntax for Anonymous Functions -``` +```ebnf SimpleExpr1 ::= `_' ``` @@ -1323,7 +1323,7 @@ include at least the expressions of the following forms: ## Statements -``` +```ebnf BlockStat ::= Import | {Annotation} [‘implicit’ | ‘lazy’] Def | {Annotation} {LocalModifier} TmplDef @@ -1380,7 +1380,7 @@ is applied to pick a unique member. ###### Type Instantiation An expression $e$ of polymorphic type -``` +```scala [$a_1$ >: $L_1$ <: $U_1 , \ldots , a_n$ >: $L_n$ <: $U_n$]$T$ ``` @@ -1557,7 +1557,7 @@ alternatives in $\mathscr{B}$. ###### Example Consider the following definitions: -``` +```scala class A extends B {} def f(x: B, y: B) = $\ldots$ def f(x: A, y: B) = $\ldots$ @@ -1569,7 +1569,7 @@ 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 -``` +```scala def f(x: B, y: A) = $\ldots$ ``` @@ -1670,14 +1670,14 @@ any one of them. ###### Example Consider the two methods: -``` +```scala def cons[A](x: A, xs: List[A]): List[A] = x :: xs def nil[B]: List[B] = Nil ``` and the definition -``` +```scala val xs = cons(1, nil) ``` @@ -1693,7 +1693,7 @@ 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 -``` +```scala List[b?] <: List[a] ``` @@ -1702,14 +1702,14 @@ that it is a variable in the constraint system. Because class `List` is covariant, the optimal solution of this constraint is -``` +```scala b = scala.Nothing ``` In a second step, one solves the following constraint system for the type parameter `a` of `cons`: -``` +```scala Int <: a? List[scala.Nothing] <: List[a?] List[a?] <: $\mathit{undefined}$ @@ -1717,7 +1717,7 @@ List[a?] <: $\mathit{undefined}$ The optimal solution of this constraint system is -``` +```scala a = Int ``` @@ -1728,7 +1728,7 @@ so `Int` is the type inferred for `a`. Consider now the definition -``` +```scala val ys = cons("abc", xs) ``` @@ -1746,7 +1746,7 @@ the second strategy is tried; `xs` is now typed with expected type In a second step, one solves the following constraint system for the type parameter `a` of `cons`: -``` +```scala String <: a? List[Int] <: List[a?] List[a?] <: $\mathit{undefined}$ @@ -1754,7 +1754,7 @@ List[a?] <: $\mathit{undefined}$ The optimal solution of this constraint system is -``` +```scala a = scala.Any ``` @@ -1774,7 +1774,7 @@ corresponding fresh name $x_i$. Second, one creates a fresh name $y_i$ for every argument type $T_i$ of the method ($i = 1 , \ldots , n$). The result of eta-conversion is then: -``` +```scala { val $x_1$ = $e_1$; $\ldots$ val $x_m$ = $e_m$; @@ -1787,7 +1787,7 @@ n$). The result of eta-conversion is then: The standard Scala library defines a trait `scala.Dynamic` which defines a member \@invokeDynamic@ as follows: -``` +```scala package scala trait Dynamic { def applyDynamic (name: String, args: Any*): Any @@ -1798,14 +1798,14 @@ trait Dynamic { Assume a selection of the form $e.x$ where the type of $e$ conforms to `scala.Dynamic`. Further assuming the selection is not followed by any function arguments, such an expression can be rewitten under the conditions given [here](#implicit-conversions) to: -``` +```scala $e$.applyDynamic("$x$") ``` If the selection is followed by some arguments, e.g. $e.x(\mathit{args})$, then that expression is rewritten to -``` +```scala $e$.applyDynamic("$x$", $\mathit{args}$) ``` -- cgit v1.2.3