From 662621e222f0a2a95516215d3b02fabf4f64354f Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Mon, 3 Oct 2016 19:16:14 +0200 Subject: [PATCH 1/9] get tut to work with Travis --- .travis.yml | 5 +++-- _config.yml | 3 ++- scripts/install-coursier.sh | 3 +++ scripts/run-tut.sh | 6 ++++++ 4 files changed, 14 insertions(+), 3 deletions(-) create mode 100755 scripts/install-coursier.sh create mode 100755 scripts/run-tut.sh diff --git a/.travis.yml b/.travis.yml index 4a2f83a0b..ebab291c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ -# opt-in to Travis new infrastructure -sudo: false +sudo: true language: ruby rvm: 2.0.0 @@ -8,7 +7,9 @@ rvm: 2.0.0 # will kick in and use `vendor`, ignoring our BUNDLE_PATH # declaration in `.bundle/config` install: +- ./scripts/install-coursier.sh - bundle install script: +- ./scripts/run-tut.sh - bundle exec jekyll build diff --git a/_config.yml b/_config.yml index 957736142..f1777603e 100644 --- a/_config.yml +++ b/_config.yml @@ -1,4 +1,6 @@ markdown: kramdown +kramdown: + input: GFM title: "Scala Documentation" description: "Documentation for the Scala programming language - Tutorials, Overviews, Cheatsheets, and more." @@ -21,4 +23,3 @@ baseurl: exclude: ["vendor"] gems: - jekyll-redirect-from - diff --git a/scripts/install-coursier.sh b/scripts/install-coursier.sh new file mode 100755 index 000000000..b0440f0f6 --- /dev/null +++ b/scripts/install-coursier.sh @@ -0,0 +1,3 @@ +#!/bin/bash +curl -L -o coursier https://git.io/vgvpD +chmod +x coursier diff --git a/scripts/run-tut.sh b/scripts/run-tut.sh new file mode 100755 index 000000000..8946dc10a --- /dev/null +++ b/scripts/run-tut.sh @@ -0,0 +1,6 @@ +#!/bin/bash +COURSIER_CLASSPATH="$(coursier fetch -p com.chuusai:shapeless_2.11:2.3.1)" + +./coursier launch -r "https://dl.bintray.com/tpolecat/maven/" org.tpolecat:tut-core_2.11:0.4.4 -- . tut-tmp '.*\.md$' -classpath "$COURSIER_CLASSPATH" + +rm -r tut-tmp From b8a575b0a250605d848ff361815bbf4cc14028ae Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Mon, 3 Oct 2016 19:42:15 +0200 Subject: [PATCH 2/9] Update run-tut.sh set coursier path correctly --- scripts/run-tut.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run-tut.sh b/scripts/run-tut.sh index 8946dc10a..7759a7fc6 100755 --- a/scripts/run-tut.sh +++ b/scripts/run-tut.sh @@ -1,5 +1,5 @@ #!/bin/bash -COURSIER_CLASSPATH="$(coursier fetch -p com.chuusai:shapeless_2.11:2.3.1)" +COURSIER_CLASSPATH="$(./coursier fetch -p com.chuusai:shapeless_2.11:2.3.1)" ./coursier launch -r "https://dl.bintray.com/tpolecat/maven/" org.tpolecat:tut-core_2.11:0.4.4 -- . tut-tmp '.*\.md$' -classpath "$COURSIER_CLASSPATH" From 736b650e2149a4a8fac9c8a7b302f96babda8c51 Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Tue, 4 Oct 2016 11:02:18 +0200 Subject: [PATCH 3/9] tutify the Scala tour The code blocks with `tut`, `tut:fail`, or `tut:nofail` are checked by tut. The others are not. --- scripts/run-tut.sh | 2 +- tutorials/tour/abstract-types.md | 82 +++++----- tutorials/tour/annotations.md | 123 ++++++++------- tutorials/tour/anonymous-function-syntax.md | 36 +++-- tutorials/tour/automatic-closures.md | 76 +++++----- tutorials/tour/case-classes.md | 92 +++++++----- tutorials/tour/classes.md | 42 +++--- tutorials/tour/compound-types.md | 38 +++-- tutorials/tour/currying.md | 34 +++-- tutorials/tour/default-parameter-values.md | 74 ++++----- .../tour/explicitly-typed-self-references.md | 140 ++++++++++-------- tutorials/tour/extractor-objects.md | 20 +-- tutorials/tour/generic-classes.md | 38 +++-- tutorials/tour/higher-order-functions.md | 28 ++-- tutorials/tour/implicit-conversions.md | 24 +-- tutorials/tour/implicit-parameters.md | 62 ++++---- tutorials/tour/inner-classes.md | 116 ++++++++------- tutorials/tour/local-type-inference.md | 50 ++++--- tutorials/tour/lower-type-bounds.md | 46 +++--- tutorials/tour/mixin-class-composition.md | 50 ++++--- tutorials/tour/named-parameters.md | 34 +++-- tutorials/tour/nested-functions.md | 26 ++-- tutorials/tour/operators.md | 24 +-- tutorials/tour/pattern-matching.md | 36 +++-- tutorials/tour/polymorphic-methods.md | 19 ++- tutorials/tour/regular-expression-patterns.md | 28 ++-- tutorials/tour/sequence-comprehensions.md | 60 ++++---- tutorials/tour/singleton-objects.md | 40 ++--- tutorials/tour/traits.md | 50 ++++--- tutorials/tour/unified-types.md | 40 ++--- tutorials/tour/upper-type-bounds.md | 36 ++--- tutorials/tour/variances.md | 38 ++--- tutorials/tour/xml-processing.md | 70 +++++---- 33 files changed, 947 insertions(+), 727 deletions(-) diff --git a/scripts/run-tut.sh b/scripts/run-tut.sh index 8946dc10a..f71877da7 100755 --- a/scripts/run-tut.sh +++ b/scripts/run-tut.sh @@ -1,5 +1,5 @@ #!/bin/bash -COURSIER_CLASSPATH="$(coursier fetch -p com.chuusai:shapeless_2.11:2.3.1)" +COURSIER_CLASSPATH="$(coursier fetch -p com.chuusai:shapeless_2.11:2.3.1 org.scala-lang.modules::scala-xml:1.0.3)" ./coursier launch -r "https://dl.bintray.com/tpolecat/maven/" org.tpolecat:tut-core_2.11:0.4.4 -- . tut-tmp '.*\.md$' -classpath "$COURSIER_CLASSPATH" diff --git a/tutorials/tour/abstract-types.md b/tutorials/tour/abstract-types.md index 7a6686089..73bf8ff91 100644 --- a/tutorials/tour/abstract-types.md +++ b/tutorials/tour/abstract-types.md @@ -14,57 +14,65 @@ tutorial-previous: inner-classes In Scala, classes are parameterized with values (the constructor parameters) and with types (if classes are [generic](generic-classes.html)). For reasons of regularity, it is not only possible to have values as object members; types along with values are members of objects. Furthermore, both forms of members can be concrete and abstract. Here is an example which defines both a deferred value definition and an abstract type definition as members of [class](traits.html) `Buffer`. - trait Buffer { - type T - val element: T - } +```tut +trait Buffer { + type T + val element: T +} +``` *Abstract types* are types whose identity is not precisely known. In the example above, we only know that each object of class `Buffer` has a type member `T`, but the definition of class `Buffer` does not reveal to what concrete type the member type `T` corresponds. Like value definitions, we can override type definitions in subclasses. This allows us to reveal more information about an abstract type by tightening the type bound (which describes possible concrete instantiations of the abstract type). In the following program we derive a class `SeqBuffer` which allows us to store only sequences in the buffer by stating that type `T` has to be a subtype of `Seq[U]` for a new abstract type `U`: - abstract class SeqBuffer extends Buffer { - type U - type T <: Seq[U] - def length = element.length - } +```tut +abstract class SeqBuffer extends Buffer { + type U + type T <: Seq[U] + def length = element.length +} +``` Traits or [classes](classes.html) with abstract type members are often used in combination with anonymous class instantiations. To illustrate this, we now look at a program which deals with a sequence buffer that refers to a list of integers: - abstract class IntSeqBuffer extends SeqBuffer { - type U = Int - } - - object AbstractTypeTest1 extends App { - def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer = - new IntSeqBuffer { - type T = List[U] - val element = List(elem1, elem2) - } - val buf = newIntSeqBuf(7, 8) - println("length = " + buf.length) - println("content = " + buf.element) - } +```tut +abstract class IntSeqBuffer extends SeqBuffer { + type U = Int +} + +object AbstractTypeTest1 extends App { + def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer = + new IntSeqBuffer { + type T = List[U] + val element = List(elem1, elem2) + } + val buf = newIntSeqBuf(7, 8) + println("length = " + buf.length) + println("content = " + buf.element) +} +``` The return type of method `newIntSeqBuf` refers to a specialization of trait `Buffer` in which type `U` is now equivalent to `Int`. We have a similar type alias in the anonymous class instantiation within the body of method `newIntSeqBuf`. Here we create a new instance of `IntSeqBuffer` in which type `T` refers to `List[Int]`. Please note that it is often possible to turn abstract type members into type parameters of classes and vice versa. Here is a version of the code above which only uses type parameters: - abstract class Buffer[+T] { - val element: T - } - abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] { - def length = element.length - } - object AbstractTypeTest2 extends App { - def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] = - new SeqBuffer[Int, List[Int]] { - val element = List(e1, e2) - } - val buf = newIntSeqBuf(7, 8) - println("length = " + buf.length) - println("content = " + buf.element) +```tut +abstract class Buffer[+T] { + val element: T +} +abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] { + def length = element.length +} +object AbstractTypeTest2 extends App { + def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] = + new SeqBuffer[Int, List[Int]] { + val element = List(e1, e2) } + val buf = newIntSeqBuf(7, 8) + println("length = " + buf.length) + println("content = " + buf.element) +} +``` Note that we have to use [variance annotations](variances.html) here; otherwise we would not be able to hide the concrete sequence implementation type of the object returned from method `newIntSeqBuf`. Furthermore, there are cases where it is not possible to replace abstract types with type parameters. diff --git a/tutorials/tour/annotations.md b/tutorials/tour/annotations.md index cad71a396..1319e6672 100644 --- a/tutorials/tour/annotations.md +++ b/tutorials/tour/annotations.md @@ -38,39 +38,45 @@ In the following example we add the `throws` annotation to the definition of the > A Java compiler checks that a program contains handlers for [checked exceptions](http://docs.oracle.com/javase/specs/jls/se5.0/html/exceptions.html) by analyzing which checked exceptions can result from execution of a method or constructor. For each checked exception which is a possible result, the **throws** clause for the method or constructor _must_ mention the class of that exception or one of the superclasses of the class of that exception. > Since Scala has no checked exceptions, Scala methods _must_ be annotated with one or more `throws` annotations such that Java code can catch exceptions thrown by a Scala method. - package examples - import java.io._ - class Reader(fname: String) { - private val in = new BufferedReader(new FileReader(fname)) - @throws(classOf[IOException]) - def read() = in.read() - } +``` +package examples +import java.io._ +class Reader(fname: String) { + private val in = new BufferedReader(new FileReader(fname)) + @throws(classOf[IOException]) + def read() = in.read() +} +``` The following Java program prints out the contents of the file whose name is passed as the first argument to the `main` method. - package test; - import examples.Reader; // Scala class !! - public class AnnotaTest { - public static void main(String[] args) { - try { - Reader in = new Reader(args[0]); - int c; - while ((c = in.read()) != -1) { - System.out.print((char) c); - } - } catch (java.io.IOException e) { - System.out.println(e.getMessage()); +``` +package test; +import examples.Reader; // Scala class !! +public class AnnotaTest { + public static void main(String[] args) { + try { + Reader in = new Reader(args[0]); + int c; + while ((c = in.read()) != -1) { + System.out.print((char) c); } + } catch (java.io.IOException e) { + System.out.println(e.getMessage()); } } +} +``` Commenting out the `throws` annotation in the class Reader produces the following error message when compiling the Java main program: - Main.java:11: exception java.io.IOException is never thrown in body of - corresponding try statement - } catch (java.io.IOException e) { - ^ - 1 error +``` +Main.java:11: exception java.io.IOException is never thrown in body of +corresponding try statement + } catch (java.io.IOException e) { + ^ +1 error +``` ### Java Annotations ### @@ -78,53 +84,64 @@ Commenting out the `throws` annotation in the class Reader produces the followin Java 1.5 introduced user-defined metadata in the form of [annotations](http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html). A key feature of annotations is that they rely on specifying name-value pairs to initialize their elements. For instance, if we need an annotation to track the source of some class we might define it as - @interface Source { - public String URL(); - public String mail(); - } +``` +@interface Source { + public String URL(); + public String mail(); +} +``` And then apply it as follows - @Source(URL = "http://coders.com/", - mail = "support@coders.com") - public class MyClass extends HisClass ... +``` +@Source(URL = "http://coders.com/", + mail = "support@coders.com") +public class MyClass extends HisClass ... +``` An annotation application in Scala looks like a constructor invocation, for instantiating a Java annotation one has to use named arguments: - @Source(URL = "http://coders.com/", - mail = "support@coders.com") - class MyScalaClass ... +``` +@Source(URL = "http://coders.com/", + mail = "support@coders.com") +class MyScalaClass ... +``` This syntax is quite tedious if the annotation contains only one element (without default value) so, by convention, if the name is specified as `value` it can be applied in Java using a constructor-like syntax: - @interface SourceURL { - public String value(); - public String mail() default ""; - } +``` +@interface SourceURL { + public String value(); + public String mail() default ""; +} +``` And then apply it as follows - @SourceURL("http://coders.com/") - public class MyClass extends HisClass ... +``` +@SourceURL("http://coders.com/") +public class MyClass extends HisClass ... +``` In this case, Scala provides the same possibility - @SourceURL("http://coders.com/") - class MyScalaClass ... +``` +@SourceURL("http://coders.com/") +class MyScalaClass ... +``` The `mail` element was specified with a default value so we need not explicitly provide a value for it. However, if we need to do it we can not mix-and-match the two styles in Java: - @SourceURL(value = "http://coders.com/", - mail = "support@coders.com") - public class MyClass extends HisClass ... +``` +@SourceURL(value = "http://coders.com/", + mail = "support@coders.com") +public class MyClass extends HisClass ... +``` Scala provides more flexibility in this respect - @SourceURL("http://coders.com/", - mail = "support@coders.com") - class MyScalaClass ... - - - - - +``` +@SourceURL("http://coders.com/", + mail = "support@coders.com") + class MyScalaClass ... +``` diff --git a/tutorials/tour/anonymous-function-syntax.md b/tutorials/tour/anonymous-function-syntax.md index a9c6d76e3..7d2f12138 100644 --- a/tutorials/tour/anonymous-function-syntax.md +++ b/tutorials/tour/anonymous-function-syntax.md @@ -12,30 +12,42 @@ tutorial-previous: mixin-class-composition Scala provides a relatively lightweight syntax for defining anonymous functions. The following expression creates a successor function for integers: - (x: Int) => x + 1 +```tut +(x: Int) => x + 1 +``` This is a shorthand for the following anonymous class definition: - new Function1[Int, Int] { - def apply(x: Int): Int = x + 1 - } +```tut +new Function1[Int, Int] { + def apply(x: Int): Int = x + 1 +} +``` It is also possible to define functions with multiple parameters: - (x: Int, y: Int) => "(" + x + ", " + y + ")" +```tut +(x: Int, y: Int) => "(" + x + ", " + y + ")" +``` or with no parameter: - () => { System.getProperty("user.dir") } +```tut +() => { System.getProperty("user.dir") } +``` There is also a very lightweight way to write function types. Here are the types of the three functions defined above: - Int => Int - (Int, Int) => String - () => String +``` +Int => Int +(Int, Int) => String +() => String +``` This syntax is a shorthand for the following types: - Function1[Int, Int] - Function2[Int, Int, String] - Function0[String] +``` +Function1[Int, Int] +Function2[Int, Int, String] +Function0[String] +``` diff --git a/tutorials/tour/automatic-closures.md b/tutorials/tour/automatic-closures.md index 68065043f..4a487b272 100644 --- a/tutorials/tour/automatic-closures.md +++ b/tutorials/tour/automatic-closures.md @@ -14,18 +14,20 @@ Scala allows parameterless function names as parameters of methods. When such a The following code demonstrates this mechanism: - object TargetTest1 extends App { - def whileLoop(cond: => Boolean)(body: => Unit): Unit = - if (cond) { - body - whileLoop(cond)(body) - } - var i = 10 - whileLoop (i > 0) { - println(i) - i -= 1 - } +```tut +object TargetTest1 extends App { + def whileLoop(cond: => Boolean)(body: => Unit): Unit = + if (cond) { + body + whileLoop(cond)(body) } + var i = 10 + whileLoop (i > 0) { + println(i) + i -= 1 + } +} +``` The function `whileLoop` takes two parameters `cond` and `body`. When the function is applied, the actual parameters do not get evaluated. But whenever the formal parameters are used in the body of `whileLoop`, the implicitly created nullary functions will be evaluated instead. Thus, our method `whileLoop` implements a Java-like while-loop with a recursive implementation scheme. @@ -33,34 +35,38 @@ We can combine the use of [infix/postfix operators](operators.html) with this me Here is the implementation of a loop-unless statement: - object TargetTest2 extends App { - def loop(body: => Unit): LoopUnlessCond = - new LoopUnlessCond(body) - protected class LoopUnlessCond(body: => Unit) { - def unless(cond: => Boolean) { - body - if (!cond) unless(cond) - } - } - var i = 10 - loop { - println("i = " + i) - i -= 1 - } unless (i == 0) +```tut +object TargetTest2 extends App { + def loop(body: => Unit): LoopUnlessCond = + new LoopUnlessCond(body) + protected class LoopUnlessCond(body: => Unit) { + def unless(cond: => Boolean) { + body + if (!cond) unless(cond) } + } + var i = 10 + loop { + println("i = " + i) + i -= 1 + } unless (i == 0) +} +``` The `loop` function just accepts a body of a loop and returns an instance of class `LoopUnlessCond` (which encapsulates this body object). Note that the body didn't get evaluated yet. Class `LoopUnlessCond` has a method `unless` which we can use as a *infix operator*. This way, we achieve a quite natural syntax for our new loop: `loop { < stats > } unless ( < cond > )`. Here's the output when `TargetTest2` gets executed: - i = 10 - i = 9 - i = 8 - i = 7 - i = 6 - i = 5 - i = 4 - i = 3 - i = 2 - i = 1 +``` +i = 10 +i = 9 +i = 8 +i = 7 +i = 6 +i = 5 +i = 4 +i = 3 +i = 2 +i = 1 +``` diff --git a/tutorials/tour/case-classes.md b/tutorials/tour/case-classes.md index 65e213b9e..bb732efd0 100644 --- a/tutorials/tour/case-classes.md +++ b/tutorials/tour/case-classes.md @@ -14,64 +14,76 @@ Scala supports the notion of _case classes_. Case classes are regular classes wh Here is an example for a class hierarchy which consists of an abstract super class `Term` and three concrete case classes `Var`, `Fun`, and `App`. - abstract class Term - case class Var(name: String) extends Term - case class Fun(arg: String, body: Term) extends Term - case class App(f: Term, v: Term) extends Term +```tut +abstract class Term +case class Var(name: String) extends Term +case class Fun(arg: String, body: Term) extends Term +case class App(f: Term, v: Term) extends Term +``` This class hierarchy can be used to represent terms of the [untyped lambda calculus](https://en.wikipedia.org/wiki/Lambda_calculus). To facilitate the construction of case class instances, Scala does not require that the `new` primitive is used. One can simply use the class name as a function. Here is an example: - Fun("x", Fun("y", App(Var("x"), Var("y")))) +```tut +Fun("x", Fun("y", App(Var("x"), Var("y")))) +``` The constructor parameters of case classes are treated as public values and can be accessed directly. - val x = Var("x") - println(x.name) +```tut +val x = Var("x") +println(x.name) +``` For every case class the Scala compiler generates an `equals` method which implements structural equality and a `toString` method. For instance: - val x1 = Var("x") - val x2 = Var("x") - val y1 = Var("y") - println("" + x1 + " == " + x2 + " => " + (x1 == x2)) - println("" + x1 + " == " + y1 + " => " + (x1 == y1)) +```tut +val x1 = Var("x") +val x2 = Var("x") +val y1 = Var("y") +println("" + x1 + " == " + x2 + " => " + (x1 == x2)) +println("" + x1 + " == " + y1 + " => " + (x1 == y1)) +``` will print - Var(x) == Var(x) => true - Var(x) == Var(y) => false +``` +Var(x) == Var(x) => true +Var(x) == Var(y) => false +``` It only makes sense to define case classes if pattern matching is used to decompose data structures. The following [object](singleton-objects.html) defines a pretty printer function for our lambda calculus representation: - object TermTest extends scala.App { - def printTerm(term: Term) { - term match { - case Var(n) => - print(n) - case Fun(x, b) => - print("^" + x + ".") - printTerm(b) - case App(f, v) => - print("(") - printTerm(f) - print(" ") - printTerm(v) - print(")") - } - } - def isIdentityFun(term: Term): Boolean = term match { - case Fun(x, Var(y)) if x == y => true - case _ => false - } - val id = Fun("x", Var("x")) - val t = Fun("x", Fun("y", App(Var("x"), Var("y")))) - printTerm(t) - println - println(isIdentityFun(id)) - println(isIdentityFun(t)) +```tut +object TermTest extends scala.App { + def printTerm(term: Term) { + term match { + case Var(n) => + print(n) + case Fun(x, b) => + print("^" + x + ".") + printTerm(b) + case App(f, v) => + print("(") + printTerm(f) + print(" ") + printTerm(v) + print(")") } + } + def isIdentityFun(term: Term): Boolean = term match { + case Fun(x, Var(y)) if x == y => true + case _ => false + } + val id = Fun("x", Var("x")) + val t = Fun("x", Fun("y", App(Var("x"), Var("y")))) + printTerm(t) + println + println(isIdentityFun(id)) + println(isIdentityFun(t)) +} +``` In our example, the function `printTerm` is expressed as a pattern matching statement starting with the `match` keyword and consisting of sequences of `case Pattern => Body` clauses. The program above also defines a function `isIdentityFun` which checks if a given term corresponds to a simple identity function. This example uses deep patterns and guards. After matching a pattern with a given value, the guard (defined after the keyword `if`) is evaluated. If it returns `true`, the match succeeds; otherwise, it fails and the next pattern will be tried. diff --git a/tutorials/tour/classes.md b/tutorials/tour/classes.md index fbb2b28aa..9bc0a32f3 100644 --- a/tutorials/tour/classes.md +++ b/tutorials/tour/classes.md @@ -13,14 +13,16 @@ tutorial-previous: unified-types Classes in Scala are static templates that can be instantiated into many objects at runtime. Here is a class definition which defines a class `Point`: - class Point(var x: Int, var y: Int) { - def move(dx: Int, dy: Int): Unit = { - x = x + dx - y = y + dy - } - override def toString: String = - "(" + x + ", " + y + ")" - } +```tut +class Point(var x: Int, var y: Int) { + def move(dx: Int, dy: Int): Unit = { + x = x + dx + y = y + dy + } + override def toString: String = + "(" + x + ", " + y + ")" +} +``` Classes in Scala are parameterized with constructor arguments. The code above defines two constructor arguments, `x` and `y`; they are both visible in the whole body of the class. @@ -30,18 +32,22 @@ Note that in Scala, it isn't necessary to say `return` in order to return a valu Classes are instantiated with the `new` primitive, as follows: - object Classes { - def main(args: Array[String]) { - val pt = new Point(1, 2) - println(pt) - pt.move(10, 10) - println(pt) - } - } +```tut +object Classes { + def main(args: Array[String]) { + val pt = new Point(1, 2) + println(pt) + pt.move(10, 10) + println(pt) + } +} +``` The program defines an executable application Classes in form of a top-level singleton object with a `main` method. The `main` method creates a new `Point` and stores it in value `pt`. Note that values defined with the `val` construct are different from variables defined with the `var` construct (see class `Point` above) in that they do not allow updates; i.e. the value is constant. Here is the output of the program: - (1, 2) - (11, 12) +``` +(1, 2) +(11, 12) +``` diff --git a/tutorials/tour/compound-types.md b/tutorials/tour/compound-types.md index 6b273fe4a..ffa698be7 100644 --- a/tutorials/tour/compound-types.md +++ b/tutorials/tour/compound-types.md @@ -14,30 +14,36 @@ Sometimes it is necessary to express that the type of an object is a subtype of Suppose we have two traits `Cloneable` and `Resetable`: - trait Cloneable extends java.lang.Cloneable { - override def clone(): Cloneable = { - super.clone().asInstanceOf[Cloneable] - } - } - trait Resetable { - def reset: Unit - } +```tut +trait Cloneable extends java.lang.Cloneable { + override def clone(): Cloneable = { + super.clone().asInstanceOf[Cloneable] + } +} +trait Resetable { + def reset: Unit +} +``` Now suppose we want to write a function `cloneAndReset` which takes an object, clones it and resets the original object: - def cloneAndReset(obj: ?): Cloneable = { - val cloned = obj.clone() - obj.reset - cloned - } +``` +def cloneAndReset(obj: ?): Cloneable = { + val cloned = obj.clone() + obj.reset + cloned +} +``` The question arises what the type of the parameter `obj` is. If it's `Cloneable` then the object can be `clone`d, but not `reset`; if it's `Resetable` we can `reset` it, but there is no `clone` operation. To avoid type casts in such a situation, we can specify the type of `obj` to be both `Cloneable` and `Resetable`. This compound type is written like this in Scala: `Cloneable with Resetable`. Here's the updated function: - def cloneAndReset(obj: Cloneable with Resetable): Cloneable = { - //... - } +``` +def cloneAndReset(obj: Cloneable with Resetable): Cloneable = { + //... +} +``` Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members. The general form is: `A with B with C ... { refinement }` diff --git a/tutorials/tour/currying.md b/tutorials/tour/currying.md index aa72d715a..a8ab2b331 100644 --- a/tutorials/tour/currying.md +++ b/tutorials/tour/currying.md @@ -14,23 +14,27 @@ Methods may define multiple parameter lists. When a method is called with a fewe Here is an example: - object CurryTest extends App { - - def filter(xs: List[Int], p: Int => Boolean): List[Int] = - if (xs.isEmpty) xs - else if (p(xs.head)) xs.head :: filter(xs.tail, p) - else filter(xs.tail, p) - - def modN(n: Int)(x: Int) = ((x % n) == 0) - - val nums = List(1, 2, 3, 4, 5, 6, 7, 8) - println(filter(nums, modN(2))) - println(filter(nums, modN(3))) - } +```tut +object CurryTest extends App { + + def filter(xs: List[Int], p: Int => Boolean): List[Int] = + if (xs.isEmpty) xs + else if (p(xs.head)) xs.head :: filter(xs.tail, p) + else filter(xs.tail, p) + + def modN(n: Int)(x: Int) = ((x % n) == 0) + + val nums = List(1, 2, 3, 4, 5, 6, 7, 8) + println(filter(nums, modN(2))) + println(filter(nums, modN(3))) +} +``` _Note: method `modN` is partially applied in the two `filter` calls; i.e. only its first argument is actually applied. The term `modN(2)` yields a function of type `Int => Boolean` and is thus a possible candidate for the second argument of function `filter`._ Here's the output of the program above: - List(2,4,6,8) - List(3,6) +``` +List(2,4,6,8) +List(3,6) +``` diff --git a/tutorials/tour/default-parameter-values.md b/tutorials/tour/default-parameter-values.md index 5430baf46..5cd02d40a 100644 --- a/tutorials/tour/default-parameter-values.md +++ b/tutorials/tour/default-parameter-values.md @@ -14,53 +14,59 @@ Scala provides the ability to give parameters default values that can be used to In Java, one tends to see a lot of overloaded methods that only serve to provide default values for certain parameters of a large method. This is especially true with constructors: - public class HashMap { - public HashMap(Map m); - /** Create a new HashMap with default capacity (16) - * and loadFactor (0.75) - */ - public HashMap(); - /** Create a new HashMap with default loadFactor (0.75) */ - public HashMap(int initialCapacity); - public HashMap(int initialCapacity, float loadFactor); - } +```java +public class HashMap { + public HashMap(Map m); + /** Create a new HashMap with default capacity (16) + * and loadFactor (0.75) + */ + public HashMap(); + /** Create a new HashMap with default loadFactor (0.75) */ + public HashMap(int initialCapacity); + public HashMap(int initialCapacity, float loadFactor); +} +``` There's really only two constructors here; one that takes another map, and one that takes a capacity and load factor. The third and fourth constructors are there to allow users of HashMap to create instances with the probably-good-for-most-cases defaults of both load factor and capacity. More problematic is that the values used for defaults are in both the Javadoc *and* the code. Keeping this up to date is easily forgotten. A typical pattern around this would be to add public constants whose values will show up in the Javadoc: - public class HashMap { - public static final int DEFAULT_CAPACITY = 16; - public static final float DEFAULT_LOAD_FACTOR = 0.75; - - public HashMap(Map m); - /** Create a new HashMap with default capacity (16) - * and loadFactor (0.75) - */ - public HashMap(); - /** Create a new HashMap with default loadFactor (0.75) */ - public HashMap(int initialCapacity); - public HashMap(int initialCapacity, float loadFactor); - } +```java +public class HashMap { + public static final int DEFAULT_CAPACITY = 16; + public static final float DEFAULT_LOAD_FACTOR = 0.75; + + public HashMap(Map m); + /** Create a new HashMap with default capacity (16) + * and loadFactor (0.75) + */ + public HashMap(); + /** Create a new HashMap with default loadFactor (0.75) */ + public HashMap(int initialCapacity); + public HashMap(int initialCapacity, float loadFactor); +} +``` While this keeps us from repeating ourselves, it's less than expressive. Scala adds direct support for this: - class HashMap[K,V](initialCapacity:Int = 16, loadFactor:Float = 0.75f) { - } +```tut +class HashMap[K,V](initialCapacity:Int = 16, loadFactor:Float = 0.75f) { +} - // Uses the defaults - val m1 = new HashMap[String,Int] +// Uses the defaults +val m1 = new HashMap[String,Int] - // initialCapacity 20, default loadFactor - val m2= new HashMap[String,Int](20) +// initialCapacity 20, default loadFactor +val m2= new HashMap[String,Int](20) - // overriding both - val m3 = new HashMap[String,Int](20,0.8f) +// overriding both +val m3 = new HashMap[String,Int](20,0.8f) - // override only the loadFactor via - // named arguments - val m4 = new HashMap[String,Int](loadFactor = 0.8f) +// override only the loadFactor via +// named arguments +val m4 = new HashMap[String,Int](loadFactor = 0.8f) +``` Note how we can take advantage of *any* default value by using [named parameters]({{ site.baseurl }}/tutorials/tour/named-parameters.html). diff --git a/tutorials/tour/explicitly-typed-self-references.md b/tutorials/tour/explicitly-typed-self-references.md index f6b257775..8c5379304 100644 --- a/tutorials/tour/explicitly-typed-self-references.md +++ b/tutorials/tour/explicitly-typed-self-references.md @@ -14,44 +14,48 @@ When developing extensible software it is sometimes handy to declare the type of Here is a definition describing graphs: - abstract class Graph { - type Edge - type Node <: NodeIntf - abstract class NodeIntf { - def connectWith(node: Node): Edge - } - def nodes: List[Node] - def edges: List[Edge] - def addNode: Node - } +```tut +abstract class Graph { + type Edge + type Node <: NodeIntf + abstract class NodeIntf { + def connectWith(node: Node): Edge + } + def nodes: List[Node] + def edges: List[Edge] + def addNode: Node +} +``` Graphs consist of a list of nodes and edges where both the node and the edge type are left abstract. The use of [abstract types](abstract-types.html) allows implementations of trait Graph to provide their own concrete classes for nodes and edges. Furthermore, there is a method `addNode` for adding new nodes to a graph. Nodes are connected using method `connectWith`. A possible implementation of class `Graph` is given in the next class: - abstract class DirectedGraph extends Graph { - type Edge <: EdgeImpl - class EdgeImpl(origin: Node, dest: Node) { - def from = origin - def to = dest - } - class NodeImpl extends NodeIntf { - def connectWith(node: Node): Edge = { - val edge = newEdge(this, node) - edges = edge :: edges - edge - } - } - protected def newNode: Node - protected def newEdge(from: Node, to: Node): Edge - var nodes: List[Node] = Nil - var edges: List[Edge] = Nil - def addNode: Node = { - val node = newNode - nodes = node :: nodes - node - } +```tut:fail +abstract class DirectedGraph extends Graph { + type Edge <: EdgeImpl + class EdgeImpl(origin: Node, dest: Node) { + def from = origin + def to = dest + } + class NodeImpl extends NodeIntf { + def connectWith(node: Node): Edge = { + val edge = newEdge(this, node) + edges = edge :: edges + edge } + } + protected def newNode: Node + protected def newEdge(from: Node, to: Node): Edge + var nodes: List[Node] = Nil + var edges: List[Edge] = Nil + def addNode: Node = { + val node = newNode + nodes = node :: nodes + node + } +} +``` Class `DirectedGraph` specializes the `Graph` class by providing a partial implementation. The implementation is only partial, because we would like to be able to extend `DirectedGraph` further. Therefore this class leaves all implementation details open and thus both the edge and the node type are left abstract. Nevertheless, class `DirectedGraph` reveals some additional details about the implementation of the edge type by tightening the bound to class `EdgeImpl`. Furthermore, we have some preliminary implementations of edges and nodes represented by the classes `EdgeImpl` and `NodeImpl`. Since it is necessary to create new node and edge objects within our partial graph implementation, we also have to add the factory methods `newNode` and `newEdge`. The methods `addNode` and `connectWith` are both defined in terms of these factory methods. A closer look at the implementation of method `connectWith` reveals that for creating an edge, we have to pass the self reference `this` to the factory method `newEdge`. But `this` is assigned the type `NodeImpl`, so it's not compatible with type `Node` which is required by the corresponding factory method. As a consequence, the program above is not well-formed and the Scala compiler will issue an error message. @@ -59,42 +63,60 @@ In Scala it is possible to tie a class to another type (which will be implemente Here is the fixed program: - abstract class DirectedGraph extends Graph { - ... - class NodeImpl extends NodeIntf { - self: Node => - def connectWith(node: Node): Edge = { - val edge = newEdge(this, node) // now legal - edges = edge :: edges - edge - } - } - ... +```tut +abstract class DirectedGraph extends Graph { + type Edge <: EdgeImpl + class EdgeImpl(origin: Node, dest: Node) { + def from = origin + def to = dest + } + class NodeImpl extends NodeIntf { + self: Node => // new line + def connectWith(node: Node): Edge = { + val edge = newEdge(this, node) // now legal + edges = edge :: edges + edge } + } + protected def newNode: Node + protected def newEdge(from: Node, to: Node): Edge + var nodes: List[Node] = Nil + var edges: List[Edge] = Nil + def addNode: Node = { + val node = newNode + nodes = node :: nodes + node + } +} +``` In this new definition of class `NodeImpl`, `this` has type `Node`. Since type `Node` is abstract and we therefore don't know yet if `NodeImpl` is really a subtype of `Node`, the type system of Scala will not allow us to instantiate this class. But nevertheless, we state with the explicit type annotation of this that at some point, (a subclass of) `NodeImpl` has to denote a subtype of type `Node` in order to be instantiatable. Here is a concrete specialization of `DirectedGraph` where all abstract class members are turned into concrete ones: - class ConcreteDirectedGraph extends DirectedGraph { - type Edge = EdgeImpl - type Node = NodeImpl - protected def newNode: Node = new NodeImpl - protected def newEdge(f: Node, t: Node): Edge = - new EdgeImpl(f, t) - } +```tut +class ConcreteDirectedGraph extends DirectedGraph { + type Edge = EdgeImpl + type Node = NodeImpl + protected def newNode: Node = new NodeImpl + protected def newEdge(f: Node, t: Node): Edge = + new EdgeImpl(f, t) +} +``` Please note that in this class, we can instantiate `NodeImpl` because now we know that `NodeImpl` denotes a subtype of type `Node` (which is simply an alias for `NodeImpl`). Here is a usage example of class `ConcreteDirectedGraph`: - object GraphTest extends App { - val g: Graph = new ConcreteDirectedGraph - val n1 = g.addNode - val n2 = g.addNode - val n3 = g.addNode - n1.connectWith(n2) - n2.connectWith(n3) - n1.connectWith(n3) - } +```tut +object GraphTest extends App { + val g: Graph = new ConcreteDirectedGraph + val n1 = g.addNode + val n2 = g.addNode + val n3 = g.addNode + n1.connectWith(n2) + n2.connectWith(n3) + n1.connectWith(n3) +} +``` diff --git a/tutorials/tour/extractor-objects.md b/tutorials/tour/extractor-objects.md index 52194195d..736c1bf1a 100644 --- a/tutorials/tour/extractor-objects.md +++ b/tutorials/tour/extractor-objects.md @@ -12,15 +12,17 @@ tutorial-previous: regular-expression-patterns In Scala, patterns can be defined independently of case classes. To this end, a method named unapply is defined to yield a so-called extractor. An extractor can be thought of as a special method that reverses the effect of applying a particular object on some inputs. Its purpose is to 'extract' the inputs that were present before the 'apply' operation. For instance, the following code defines an extractor [object](singleton-objects.html) Twice. - object Twice { - def apply(x: Int): Int = x * 2 - def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None - } - - object TwiceTest extends App { - val x = Twice(21) - x match { case Twice(n) => Console.println(n) } // prints 21 - } +```tut +object Twice { + def apply(x: Int): Int = x * 2 + def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None +} + +object TwiceTest extends App { + val x = Twice(21) + x match { case Twice(n) => Console.println(n) } // prints 21 +} +``` There are two syntactic conventions at work here: diff --git a/tutorials/tour/generic-classes.md b/tutorials/tour/generic-classes.md index 4c1231a30..9005e4344 100644 --- a/tutorials/tour/generic-classes.md +++ b/tutorials/tour/generic-classes.md @@ -13,29 +13,35 @@ tutorial-previous: sequence-comprehensions Like in Java 5 (aka. [JDK 1.5](http://java.sun.com/j2se/1.5/)), Scala has built-in support for classes parameterized with types. Such generic classes are particularly useful for the development of collection classes. Here is an example which demonstrates this: - class Stack[T] { - var elems: List[T] = Nil - def push(x: T) { elems = x :: elems } - def top: T = elems.head - def pop() { elems = elems.tail } - } +```tut +class Stack[T] { + var elems: List[T] = Nil + def push(x: T) { elems = x :: elems } + def top: T = elems.head + def pop() { elems = elems.tail } +} +``` Class `Stack` models imperative (mutable) stacks of an arbitrary element type `T`. The type parameters enforces that only legal elements (that are of type `T`) are pushed onto the stack. Similarly, with type parameters we can express that method `top` will only yield elements of the given type. Here are some usage examples: - object GenericsTest extends App { - val stack = new Stack[Int] - stack.push(1) - stack.push('a') - println(stack.top) - stack.pop() - println(stack.top) - } +```tut +object GenericsTest extends App { + val stack = new Stack[Int] + stack.push(1) + stack.push('a') + println(stack.top) + stack.pop() + println(stack.top) +} +``` The output of this program will be: - 97 - 1 +``` +97 +1 +``` _Note: subtyping of generic types is *invariant*. This means that if we have a stack of characters of type `Stack[Char]` then it cannot be used as an integer stack of type `Stack[Int]`. This would be unsound because it would enable us to enter true integers into the character stack. To conclude, `Stack[T]` is only a subtype of `Stack[S]` if and only if `S = T`. Since this can be quite restrictive, Scala offers a [type parameter annotation mechanism](variances.html) to control the subtyping behavior of generic types._ diff --git a/tutorials/tour/higher-order-functions.md b/tutorials/tour/higher-order-functions.md index ee379b39d..03f16391e 100644 --- a/tutorials/tour/higher-order-functions.md +++ b/tutorials/tour/higher-order-functions.md @@ -12,24 +12,30 @@ tutorial-previous: anonymous-function-syntax Scala allows the definition of higher-order functions. These are functions that _take other functions as parameters_, or whose _result is a function_. Here is a function `apply` which takes another function `f` and a value `v` and applies function `f` to `v`: - def apply(f: Int => String, v: Int) = f(v) +```tut +def apply(f: Int => String, v: Int) = f(v) +``` _Note: methods are automatically coerced to functions if the context requires this._ Here is another example: - class Decorator(left: String, right: String) { - def layout[A](x: A) = left + x.toString() + right - } - - object FunTest extends App { - def apply(f: Int => String, v: Int) = f(v) - val decorator = new Decorator("[", "]") - println(apply(decorator.layout, 7)) - } +```tut +class Decorator(left: String, right: String) { + def layout[A](x: A) = left + x.toString() + right +} + +object FunTest extends App { + def apply(f: Int => String, v: Int) = f(v) + val decorator = new Decorator("[", "]") + println(apply(decorator.layout, 7)) +} +``` Execution yields the output: - [7] +``` +[7] +``` In this example, the method `decorator.layout` is coerced automatically to a value of type `Int => String` as required by method `apply`. Please note that method `decorator.layout` is a _polymorphic method_ (i.e. it abstracts over some of its signature types) and the Scala compiler has to instantiate its method type first appropriately. diff --git a/tutorials/tour/implicit-conversions.md b/tutorials/tour/implicit-conversions.md index 84c48bba4..aa53946c5 100644 --- a/tutorials/tour/implicit-conversions.md +++ b/tutorials/tour/implicit-conversions.md @@ -22,22 +22,28 @@ In the second case, a conversion `c` is searched for which is applicable to `e` The following operation on the two lists xs and ys of type `List[Int]` is legal: - xs <= ys +``` +xs <= ys +``` assuming the implicit methods `list2ordered` and `int2ordered` defined below are in scope: - implicit def list2ordered[A](x: List[A]) - (implicit elem2ordered: A => Ordered[A]): Ordered[List[A]] = - new Ordered[List[A]] { /* .. */ } - - implicit def int2ordered(x: Int): Ordered[Int] = - new Ordered[Int] { /* .. */ } +``` +implicit def list2ordered[A](x: List[A]) + (implicit elem2ordered: A => Ordered[A]): Ordered[List[A]] = + new Ordered[List[A]] { /* .. */ } + +implicit def int2ordered(x: Int): Ordered[Int] = + new Ordered[Int] { /* .. */ } +``` The implicitly imported object `scala.Predef` declares several predefined types (e.g. `Pair`) and methods (e.g. `assert`) but also several implicit conversions. For example, when calling a Java method that expects a `java.lang.Integer`, you are free to pass it a `scala.Int` instead. That's because Predef includes the following implicit conversions: - implicit def int2Integer(x: Int) = - java.lang.Integer.valueOf(x) +```tut +implicit def int2Integer(x: Int) = + java.lang.Integer.valueOf(x) +``` To define your own implicit conversions, you must first `import scala.language.implicitConversions` (or invoke the compiler with `-language:implicitConversions`). The feature must be explicitly enabled because it has pitfalls if used indiscriminately. diff --git a/tutorials/tour/implicit-parameters.md b/tutorials/tour/implicit-parameters.md index 226bf951f..471b5e638 100644 --- a/tutorials/tour/implicit-parameters.md +++ b/tutorials/tour/implicit-parameters.md @@ -19,35 +19,39 @@ The actual arguments that are eligible to be passed to an implicit parameter fal In the following example we define a method `sum` which computes the sum of a list of elements using the monoid's `add` and `unit` operations. Please note that implicit values can not be top-level, they have to be members of a template. - /** This example uses a structure from abstract algebra to show how implicit parameters work. A semigroup is an algebraic structure on a set A with an (associative) operation, called add here, that combines a pair of A's and returns another A. */ - abstract class SemiGroup[A] { - def add(x: A, y: A): A - } - /** A monoid is a semigroup with a distinguished element of A, called unit, that when combined with any other element of A returns that other element again. */ - abstract class Monoid[A] extends SemiGroup[A] { - def unit: A - } - object ImplicitTest extends App { - /** To show how implicit parameters work, we first define monoids for strings and integers. The implicit keyword indicates that the corresponding object can be used implicitly, within this scope, as a parameter of a function marked implicit. */ - 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 - } - /** This method takes a List[A] returns an A which represent the combined value of applying the monoid operation successively across the whole list. Making the parameter m implicit here means we only have to provide the xs parameter at the call site, since if we have a List[A] we know what type A actually is and therefore what type Monoid[A] is needed. We can then implicitly find whichever val or object in the current scope also has that type and use that without needing to specify it explicitly. */ - def sum[A](xs: List[A])(implicit m: Monoid[A]): A = - if (xs.isEmpty) m.unit - else m.add(xs.head, sum(xs.tail)) - - /** Here we call sum twice, with only one parameter each time. Since the second parameter of sum, m, is implicit its value is looked up in the current scope, based on the type of monoid required in each case, meaning both expressions can be fully evaluated. */ - println(sum(List(1, 2, 3))) // uses IntMonoid implicitly - println(sum(List("a", "b", "c"))) // uses StringMonoid implicitly - } +```tut +/** This example uses a structure from abstract algebra to show how implicit parameters work. A semigroup is an algebraic structure on a set A with an (associative) operation, called add here, that combines a pair of A's and returns another A. */ +abstract class SemiGroup[A] { + def add(x: A, y: A): A +} +/** A monoid is a semigroup with a distinguished element of A, called unit, that when combined with any other element of A returns that other element again. */ +abstract class Monoid[A] extends SemiGroup[A] { + def unit: A +} +object ImplicitTest extends App { + /** To show how implicit parameters work, we first define monoids for strings and integers. The implicit keyword indicates that the corresponding object can be used implicitly, within this scope, as a parameter of a function marked implicit. */ + 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 + } + /** This method takes a List[A] returns an A which represent the combined value of applying the monoid operation successively across the whole list. Making the parameter m implicit here means we only have to provide the xs parameter at the call site, since if we have a List[A] we know what type A actually is and therefore what type Monoid[A] is needed. We can then implicitly find whichever val or object in the current scope also has that type and use that without needing to specify it explicitly. */ + def sum[A](xs: List[A])(implicit m: Monoid[A]): A = + if (xs.isEmpty) m.unit + else m.add(xs.head, sum(xs.tail)) + + /** Here we call sum twice, with only one parameter each time. Since the second parameter of sum, m, is implicit its value is looked up in the current scope, based on the type of monoid required in each case, meaning both expressions can be fully evaluated. */ + println(sum(List(1, 2, 3))) // uses IntMonoid implicitly + println(sum(List("a", "b", "c"))) // uses StringMonoid implicitly +} +``` Here is the output of the Scala program: - 6 - abc +``` +6 +abc +``` diff --git a/tutorials/tour/inner-classes.md b/tutorials/tour/inner-classes.md index 6a4f75953..bd05876b5 100644 --- a/tutorials/tour/inner-classes.md +++ b/tutorials/tour/inner-classes.md @@ -12,75 +12,85 @@ tutorial-previous: lower-type-bounds In Scala it is possible to let classes have other classes as members. Opposed to Java-like languages where such inner classes are members of the enclosing class, in Scala such inner classes are bound to the outer object. To illustrate the difference, we quickly sketch the implementation of a graph datatype: - class Graph { - class Node { - var connectedNodes: List[Node] = Nil - def connectTo(node: Node) { - if (connectedNodes.find(node.equals).isEmpty) { - connectedNodes = node :: connectedNodes - } - } - } - var nodes: List[Node] = Nil - def newNode: Node = { - val res = new Node - nodes = res :: nodes - res +```tut +class Graph { + class Node { + var connectedNodes: List[Node] = Nil + def connectTo(node: Node) { + if (connectedNodes.find(node.equals).isEmpty) { + connectedNodes = node :: connectedNodes } } + } + var nodes: List[Node] = Nil + def newNode: Node = { + val res = new Node + nodes = res :: nodes + res + } +} +``` In our program, graphs are represented by a list of nodes. Nodes are objects of inner class `Node`. Each node has a list of neighbours, which get stored in the list `connectedNodes`. Now we can set up a graph with some nodes and connect the nodes incrementally: - object GraphTest extends App { - val g = new Graph - val n1 = g.newNode - val n2 = g.newNode - val n3 = g.newNode - n1.connectTo(n2) - n3.connectTo(n1) - } +```tut +object GraphTest extends App { + val g = new Graph + val n1 = g.newNode + val n2 = g.newNode + val n3 = g.newNode + n1.connectTo(n2) + n3.connectTo(n1) +} +``` We now enrich the above example with types to state explicitly what the type of the various defined entities is: - object GraphTest extends App { - val g: Graph = new Graph - val n1: g.Node = g.newNode - val n2: g.Node = g.newNode - val n3: g.Node = g.newNode - n1.connectTo(n2) - n3.connectTo(n1) - } +```tut +object GraphTest extends App { + val g: Graph = new Graph + val n1: g.Node = g.newNode + val n2: g.Node = g.newNode + val n3: g.Node = g.newNode + n1.connectTo(n2) + n3.connectTo(n1) +} +``` This code clearly shows that a node type is prefixed with its outer instance (which is object `g` in our example). If we now have two graphs, the type system of Scala does not allow us to mix nodes defined within one graph with the nodes of another graph, since the nodes of the other graph have a different type. Here is an illegal program: - object IllegalGraphTest extends App { - val g: Graph = new Graph - val n1: g.Node = g.newNode - val n2: g.Node = g.newNode - n1.connectTo(n2) // legal - val h: Graph = new Graph - val n3: h.Node = h.newNode - n1.connectTo(n3) // illegal! - } +```tut:fail +object IllegalGraphTest extends App { + val g: Graph = new Graph + val n1: g.Node = g.newNode + val n2: g.Node = g.newNode + n1.connectTo(n2) // legal + val h: Graph = new Graph + val n3: h.Node = h.newNode + n1.connectTo(n3) // illegal! +} +``` Please note that in Java the last line in the previous example program would have been correct. For nodes of both graphs, Java would assign the same type `Graph.Node`; i.e. `Node` is prefixed with class `Graph`. In Scala such a type can be expressed as well, it is written `Graph#Node`. If we want to be able to connect nodes of different graphs, we have to change the definition of our initial graph implementation in the following way: - class Graph { - class Node { - var connectedNodes: List[Graph#Node] = Nil - def connectTo(node: Graph#Node) { - if (connectedNodes.find(node.equals).isEmpty) { - connectedNodes = node :: connectedNodes - } - } - } - var nodes: List[Node] = Nil - def newNode: Node = { - val res = new Node - nodes = res :: nodes - res +```tut +class Graph { + class Node { + var connectedNodes: List[Graph#Node] = Nil + def connectTo(node: Graph#Node) { + if (connectedNodes.find(node.equals).isEmpty) { + connectedNodes = node :: connectedNodes } } + } + var nodes: List[Node] = Nil + def newNode: Node = { + val res = new Node + nodes = res :: nodes + res + } +} +``` > Please note that this program doesn't allow us to attach a node to two different graphs. If we want to remove this restriction as well, we have to change the type of variable nodes to `Graph#Node`. diff --git a/tutorials/tour/local-type-inference.md b/tutorials/tour/local-type-inference.md index 0d6e53eb5..b9afcb691 100644 --- a/tutorials/tour/local-type-inference.md +++ b/tutorials/tour/local-type-inference.md @@ -13,40 +13,50 @@ Scala has a built-in type inference mechanism which allows the programmer to omi Here is an example: - object InferenceTest1 extends App { - val x = 1 + 2 * 3 // the type of x is Int - val y = x.toString() // the type of y is String - def succ(x: Int) = x + 1 // method succ returns Int values - } +```tut +object InferenceTest1 extends App { + val x = 1 + 2 * 3 // the type of x is Int + val y = x.toString() // the type of y is String + def succ(x: Int) = x + 1 // method succ returns Int values +} +``` For recursive methods, the compiler is not able to infer a result type. Here is a program which will fail the compiler for this reason: - object InferenceTest2 { - def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1) - } +```tut:fail +object InferenceTest2 { + def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1) +} +``` It is also not compulsory to specify type parameters when [polymorphic methods](polymorphic-methods.html) are called or [generic classes](generic-classes.html) are instantiated. The Scala compiler will infer such missing type parameters from the context and from the types of the actual method/constructor parameters. Here is an example which illustrates this: - case class MyPair[A, B](x: A, y: B); - object InferenceTest3 extends App { - def id[T](x: T) = x - val p = MyPair(1, "scala") // type: MyPair[Int, String] - val q = id(1) // type: Int - } +``` +case class MyPair[A, B](x: A, y: B); +object InferenceTest3 extends App { + def id[T](x: T) = x + val p = MyPair(1, "scala") // type: MyPair[Int, String] + val q = id(1) // type: Int +} +``` The last two lines of this program are equivalent to the following code where all inferred types are made explicit: - val x: MyPair[Int, String] = MyPair[Int, String](1, "scala") - val y: Int = id[Int](1) +``` +val x: MyPair[Int, String] = MyPair[Int, String](1, "scala") +val y: Int = id[Int](1) +``` In some situations it can be quite dangerous to rely on Scala's type inference mechanism as the following program shows: - object InferenceTest4 { - var obj = null - obj = new Object() - } +```tut:fail +object InferenceTest4 { + var obj = null + obj = new Object() +} +``` This program does not compile because the type inferred for variable `obj` is `Null`. Since the only value of that type is `null`, it is impossible to make this variable refer to another value. diff --git a/tutorials/tour/lower-type-bounds.md b/tutorials/tour/lower-type-bounds.md index bb95471f6..a69cf5f44 100644 --- a/tutorials/tour/lower-type-bounds.md +++ b/tutorials/tour/lower-type-bounds.md @@ -14,36 +14,44 @@ While [upper type bounds](upper-type-bounds.html) limit a type to a subtype of a Here is an example where this is useful: - case class ListNode[T](h: T, t: ListNode[T]) { - def head: T = h - def tail: ListNode[T] = t - def prepend(elem: T): ListNode[T] = - ListNode(elem, this) - } +```tut +case class ListNode[T](h: T, t: ListNode[T]) { + def head: T = h + def tail: ListNode[T] = t + def prepend(elem: T): ListNode[T] = + ListNode(elem, this) +} +``` The program above implements a linked list with a prepend operation. Unfortunately, this type is invariant in the type parameter of class `ListNode`; i.e. `ListNode[String]` is not a subtype of `ListNode[Any]`. With the help of [variance annotations](variances.html) we can express such a subtype semantics: - case class ListNode[+T](h: T, t: ListNode[T]) { ... } +``` +case class ListNode[+T](h: T, t: ListNode[T]) { ... } +``` Unfortunately, this program does not compile, because a covariance annotation is only possible if the type variable is used only in covariant positions. Since type variable `T` appears as a parameter type of method `prepend`, this rule is broken. With the help of a *lower type bound*, though, we can implement a prepend method where `T` only appears in covariant positions. Here is the corresponding code: - case class ListNode[+T](h: T, t: ListNode[T]) { - def head: T = h - def tail: ListNode[T] = t - def prepend[U >: T](elem: U): ListNode[U] = - ListNode(elem, this) - } +```tut +case class ListNode[+T](h: T, t: ListNode[T]) { + def head: T = h + def tail: ListNode[T] = t + def prepend[U >: T](elem: U): ListNode[U] = + ListNode(elem, this) +} +``` _Note:_ the new `prepend` method has a slightly less restrictive type. It allows, for instance, to prepend an object of a supertype to an existing list. The resulting list will be a list of this supertype. Here is some code which illustrates this: - object LowerBoundTest extends App { - val empty: ListNode[Null] = ListNode(null, null) - val strList: ListNode[String] = empty.prepend("hello") - .prepend("world") - val anyList: ListNode[Any] = strList.prepend(12345) - } +```tut +object LowerBoundTest extends App { + val empty: ListNode[Null] = ListNode(null, null) + val strList: ListNode[String] = empty.prepend("hello") + .prepend("world") + val anyList: ListNode[Any] = strList.prepend(12345) +} +``` diff --git a/tutorials/tour/mixin-class-composition.md b/tutorials/tour/mixin-class-composition.md index 9b785db4c..817cabd1f 100644 --- a/tutorials/tour/mixin-class-composition.md +++ b/tutorials/tour/mixin-class-composition.md @@ -12,35 +12,43 @@ tutorial-previous: traits As opposed to languages that only support _single inheritance_, Scala has a more general notion of class reuse. Scala makes it possible to reuse the _new member definitions of a class_ (i.e. the delta in relationship to the superclass) in the definition of a new class. This is expressed as a _mixin-class composition_. Consider the following abstraction for iterators. - abstract class AbsIterator { - type T - def hasNext: Boolean - def next: T - } +```tut +abstract class AbsIterator { + type T + def hasNext: Boolean + def next: T +} +``` Next, consider a mixin class which extends `AbsIterator` with a method `foreach` which applies a given function to every element returned by the iterator. To define a class that can be used as a mixin we use the keyword `trait`. - trait RichIterator extends AbsIterator { - def foreach(f: T => Unit) { while (hasNext) f(next) } - } +```tut +trait RichIterator extends AbsIterator { + def foreach(f: T => Unit) { while (hasNext) f(next) } +} +``` Here is a concrete iterator class, which returns successive characters of a given string: - class StringIterator(s: String) extends AbsIterator { - type T = Char - private var i = 0 - def hasNext = i < s.length() - def next = { val ch = s charAt i; i += 1; ch } - } +```tut +class StringIterator(s: String) extends AbsIterator { + type T = Char + private var i = 0 + def hasNext = i < s.length() + def next = { val ch = s charAt i; i += 1; ch } +} +``` We would like to combine the functionality of `StringIterator` and `RichIterator` into a single class. With single inheritance and interfaces alone this is impossible, as both classes contain member implementations with code. Scala comes to help with its _mixin-class composition_. It allows the programmers to reuse the delta of a class definition, i.e., all new definitions that are not inherited. This mechanism makes it possible to combine `StringIterator` with `RichIterator`, as is done in the following test program which prints a column of all the characters of a given string. - object StringIteratorTest { - def main(args: Array[String]) { - class Iter extends StringIterator(args(0)) with RichIterator - val iter = new Iter - iter foreach println - } - } +```tut +object StringIteratorTest { + def main(args: Array[String]) { + class Iter extends StringIterator(args(0)) with RichIterator + val iter = new Iter + iter foreach println + } +} +``` The `Iter` class in function `main` is constructed from a mixin composition of the parents `StringIterator` and `RichIterator` with the keyword `with`. The first parent is called the _superclass_ of `Iter`, whereas the second (and every other, if present) parent is called a _mixin_. diff --git a/tutorials/tour/named-parameters.md b/tutorials/tour/named-parameters.md index 46dce8663..4fbbebf0b 100644 --- a/tutorials/tour/named-parameters.md +++ b/tutorials/tour/named-parameters.md @@ -11,26 +11,30 @@ tutorial-previous: default-parameter-values When calling methods and functions, you can use the name of the variables explicitly in the call, like so: - def printName(first:String, last:String) = { - println(first + " " + last) - } - - printName("John","Smith") - // Prints "John Smith" - printName(first = "John",last = "Smith") - // Prints "John Smith" - printName(last = "Smith",first = "John") - // Prints "John Smith" +```tut + def printName(first:String, last:String) = { + println(first + " " + last) + } + + printName("John","Smith") + // Prints "John Smith" + printName(first = "John",last = "Smith") + // Prints "John Smith" + printName(last = "Smith",first = "John") + // Prints "John Smith" +``` Note that once you are using parameter names in your calls, the order doesn't matter, so long as all parameters are named. This feature works well with [default parameter values]({{ site.baseurl }}/tutorials/tour/default-parameter-values.html): - def printName(first:String = "John", last:String = "Smith") = { - println(first + " " + last) - } +```tut + def printName(first:String = "John", last:String = "Smith") = { + println(first + " " + last) + } - printName(last = "Jones") - // Prints "John Jones" + printName(last = "Jones") + // Prints "John Jones" +``` Since you can place the parameters in any order you like, you can use the default value for parameters that come first in the parameter list. diff --git a/tutorials/tour/nested-functions.md b/tutorials/tour/nested-functions.md index 83416c35e..3737eeea7 100644 --- a/tutorials/tour/nested-functions.md +++ b/tutorials/tour/nested-functions.md @@ -12,19 +12,23 @@ tutorial-previous: higher-order-functions In Scala it is possible to nest function definitions. The following object provides a `filter` function for extracting values from a list of integers that are below a threshold value: - object FilterTest extends App { - def filter(xs: List[Int], threshold: Int) = { - def process(ys: List[Int]): List[Int] = - if (ys.isEmpty) ys - else if (ys.head < threshold) ys.head :: process(ys.tail) - else process(ys.tail) - process(xs) - } - println(filter(List(1, 9, 2, 8, 3, 7, 4), 5)) - } +```tut +object FilterTest extends App { + def filter(xs: List[Int], threshold: Int) = { + def process(ys: List[Int]): List[Int] = + if (ys.isEmpty) ys + else if (ys.head < threshold) ys.head :: process(ys.tail) + else process(ys.tail) + process(xs) + } + println(filter(List(1, 9, 2, 8, 3, 7, 4), 5)) +} +``` _Note: the nested function `process` refers to variable `threshold` defined in the outer scope as a parameter value of `filter`._ The output of this program is: - List(1,2,3,4) +``` +List(1,2,3,4) +``` diff --git a/tutorials/tour/operators.md b/tutorials/tour/operators.md index ce6b63176..b08ace482 100644 --- a/tutorials/tour/operators.md +++ b/tutorials/tour/operators.md @@ -12,20 +12,26 @@ tutorial-previous: local-type-inference Any method which takes a single parameter can be used as an *infix operator* in Scala. Here is the definition of class `MyBool` which defines three methods `and`, `or`, and `negate`. - class MyBool(x: Boolean) { - def and(that: MyBool): MyBool = if (x) that else this - def or(that: MyBool): MyBool = if (x) this else that - def negate: MyBool = new MyBool(!x) - } +```tut +class MyBool(x: Boolean) { + def and(that: MyBool): MyBool = if (x) that else this + def or(that: MyBool): MyBool = if (x) this else that + def negate: MyBool = new MyBool(!x) +} +``` It is now possible to use `and` and `or` as infix operators: - def not(x: MyBool) = x negate; // semicolon required here - def xor(x: MyBool, y: MyBool) = (x or y) and not(x and y) +```tut +def not(x: MyBool) = x negate; // semicolon required here +def xor(x: MyBool, y: MyBool) = (x or y) and not(x and y) +``` As the first line of this code shows, it is also possible to use nullary methods as postfix operators. The second line defines an `xor` function using the `and` and `or` methods as well as the new `not` function. In this example the use of _infix operators_ helps to make the definition of `xor` more readable. Here is the corresponding code in a more traditional object-oriented programming language syntax: - def not(x: MyBool) = x.negate; // semicolon required here - def xor(x: MyBool, y: MyBool) = x.or(y).and(x.and(y).negate) +```tut +def not(x: MyBool) = x.negate; // semicolon required here +def xor(x: MyBool, y: MyBool) = x.or(y).and(x.and(y).negate) +``` diff --git a/tutorials/tour/pattern-matching.md b/tutorials/tour/pattern-matching.md index c98e85b8d..5c8eed9f0 100644 --- a/tutorials/tour/pattern-matching.md +++ b/tutorials/tour/pattern-matching.md @@ -14,27 +14,31 @@ tutorial-previous: case-classes Scala has a built-in general pattern matching mechanism. It allows to match on any sort of data with a first-match policy. Here is a small example which shows how to match against an integer value: - object MatchTest1 extends App { - def matchTest(x: Int): String = x match { - case 1 => "one" - case 2 => "two" - case _ => "many" - } - println(matchTest(3)) - } +```tut +object MatchTest1 extends App { + def matchTest(x: Int): String = x match { + case 1 => "one" + case 2 => "two" + case _ => "many" + } + println(matchTest(3)) +} +``` The block with the `case` statements defines a function which maps integers to strings. The `match` keyword provides a convenient way of applying a function (like the pattern matching function above) to an object. Here is a second example which matches a value against patterns of different types: - object MatchTest2 extends App { - def matchTest(x: Any): Any = x match { - case 1 => "one" - case "two" => 2 - case y: Int => "scala.Int" - } - println(matchTest("two")) - } +```tut +object MatchTest2 extends App { + def matchTest(x: Any): Any = x match { + case 1 => "one" + case "two" => 2 + case y: Int => "scala.Int" + } + println(matchTest("two")) +} +``` The first `case` matches if `x` refers to the integer value `1`. The second `case` matches if `x` is equal to the string `"two"`. The third case consists of a typed pattern; it matches against any integer and binds the selector value `x` to the variable `y` of type integer. diff --git a/tutorials/tour/polymorphic-methods.md b/tutorials/tour/polymorphic-methods.md index 13191c023..8b707ec1a 100644 --- a/tutorials/tour/polymorphic-methods.md +++ b/tutorials/tour/polymorphic-methods.md @@ -15,13 +15,16 @@ Methods in Scala can be parameterized with both values and types. Like on the cl Here is an example: - def dup[T](x: T, n: Int): List[T] = - if (n == 0) - Nil - else - x :: dup(x, n - 1) - - println(dup[Int](3, 4)) - println(dup("three", 3)) +```tut +def dup[T](x: T, n: Int): List[T] = { + if (n == 0) + Nil + else + x :: dup(x, n - 1) +} + +println(dup[Int](3, 4)) +println(dup("three", 3)) +``` Method `dup` is parameterized with type `T` and with the value parameters `x: T` and `n: Int`. In the first call to `dup`, the programmer provides the required parameters, but as the following line shows, the programmer is not required to give actual type parameters explicitly. The type system of Scala can infer such types. This is done by looking at the types of the given value parameters and at the context where the method is called. diff --git a/tutorials/tour/regular-expression-patterns.md b/tutorials/tour/regular-expression-patterns.md index a5d1994ac..3e0e2a298 100644 --- a/tutorials/tour/regular-expression-patterns.md +++ b/tutorials/tour/regular-expression-patterns.md @@ -15,23 +15,27 @@ tutorial-previous: xml-processing Right-ignoring patterns are a useful feature to decompose any data which is either a subtype of `Seq[A]` or a case class with an iterated formal parameter, like for instance - Elem(prefix:String, label:String, attrs:MetaData, scp:NamespaceBinding, children:Node*) +``` +Elem(prefix:String, label:String, attrs:MetaData, scp:NamespaceBinding, children:Node*) +``` In those cases, Scala allows patterns having a wildcard-star `_*` in the rightmost position to stand for arbitrary long sequences. The following example demostrate a pattern match which matches a prefix of a sequence and binds the rest to the variable `rest`. - object RegExpTest1 extends App { - def containsScala(x: String): Boolean = { - val z: Seq[Char] = x - z match { - case Seq('s','c','a','l','a', rest @ _*) => - println("rest is "+rest) - true - case Seq(_*) => - false - } - } +```tut +object RegExpTest1 extends App { + def containsScala(x: String): Boolean = { + val z: Seq[Char] = x + z match { + case Seq('s','c','a','l','a', rest @ _*) => + println("rest is "+rest) + true + case Seq(_*) => + false } + } +} +``` In contrast to previous Scala versions, it is no longer allowed to have arbitrary regular expressions, for the reasons described below. diff --git a/tutorials/tour/sequence-comprehensions.md b/tutorials/tour/sequence-comprehensions.md index e53b84151..80002ac3e 100644 --- a/tutorials/tour/sequence-comprehensions.md +++ b/tutorials/tour/sequence-comprehensions.md @@ -14,46 +14,56 @@ Scala offers a lightweight notation for expressing *sequence comprehensions*. Co Here is an example: - object ComprehensionTest1 extends App { - def even(from: Int, to: Int): List[Int] = - for (i <- List.range(from, to) if i % 2 == 0) yield i - Console.println(even(0, 20)) - } +```tut +object ComprehensionTest1 extends App { + def even(from: Int, to: Int): List[Int] = + for (i <- List.range(from, to) if i % 2 == 0) yield i + Console.println(even(0, 20)) +} +``` The for-expression in function introduces a new variable `i` of type `Int` which is subsequently bound to all values of the list `List(from, from + 1, ..., to - 1)`. The guard `if i % 2 == 0` filters out all odd numbers so that the body (which only consists of the expression i) is only evaluated for even numbers. Consequently, the whole for-expression returns a list of even numbers. The program yields the following output: - List(0, 2, 4, 6, 8, 10, 12, 14, 16, 18) +``` +List(0, 2, 4, 6, 8, 10, 12, 14, 16, 18) +``` Here is a more complicated example which computes all pairs of numbers between `0` and `n-1` whose sum is equal to a given value `v`: - object ComprehensionTest2 extends App { - def foo(n: Int, v: Int) = - for (i <- 0 until n; - j <- i until n if i + j == v) yield - (i, j); - foo(20, 32) foreach { - case (i, j) => - println(s"($i, $j)") - } - } +```tut +object ComprehensionTest2 extends App { + def foo(n: Int, v: Int) = + for (i <- 0 until n; + j <- i until n if i + j == v) yield + (i, j); + foo(20, 32) foreach { + case (i, j) => + println(s"($i, $j)") + } +} +``` This example shows that comprehensions are not restricted to lists. The previous program uses iterators instead. Every datatype that supports the operations `filterWith`, `map`, and `flatMap` (with the proper types) can be used in sequence comprehensions. Here's the output of the program: - (13, 19) - (14, 18) - (15, 17) - (16, 16) +``` +(13, 19) +(14, 18) +(15, 17) +(16, 16) +``` There is also a special form of sequence comprehension which returns `Unit`. Here the bindings that are created from the list of generators and filters are used to perform side-effects. The programmer has to omit the keyword `yield` to make use of such a sequence comprehension. Here's a program which is equivalent to the previous one but uses the special for comprehension returning `Unit`: - object ComprehensionTest3 extends App { - for (i <- Iterator.range(0, 20); - j <- Iterator.range(i, 20) if i + j == 32) - println(s"($i, $j)") - } +``` +object ComprehensionTest3 extends App { + for (i <- Iterator.range(0, 20); + j <- Iterator.range(i, 20) if i + j == 32) + println(s"($i, $j)") +} +``` diff --git a/tutorials/tour/singleton-objects.md b/tutorials/tour/singleton-objects.md index ec2b3769e..ce6120479 100644 --- a/tutorials/tour/singleton-objects.md +++ b/tutorials/tour/singleton-objects.md @@ -13,11 +13,13 @@ tutorial-previous: pattern-matching Methods and values that aren't associated with individual instances of a [class](classes.html) belong in *singleton objects*, denoted by using the keyword `object` instead of `class`. - package test +``` +package test - object Blah { - def sum(l: List[Int]): Int = l.sum - } +object Blah { + def sum(l: List[Int]): Int = l.sum +} +``` This `sum` method is available globally, and can be referred to, or imported, as `test.Blah.sum`. @@ -33,14 +35,16 @@ Most singleton objects do not stand alone, but instead are associated with a cla A class and its companion object, if any, must be defined in the same source file. Like this: - class IntPair(val x: Int, val y: Int) +```tut +class IntPair(val x: Int, val y: Int) - object IntPair { - import math.Ordering +object IntPair { + import math.Ordering - implicit def ipord: Ordering[IntPair] = - Ordering.by(ip => (ip.x, ip.y)) - } + implicit def ipord: Ordering[IntPair] = + Ordering.by(ip => (ip.x, ip.y)) +} +``` It's common to see typeclass instances as [implicit values](implicit-parameters.html), such as `ipord` above, defined in the companion, when following the typeclass pattern. This is because the companion's members are included in the default implicit search for related values. @@ -50,15 +54,17 @@ It's common to see typeclass instances as [implicit values](implicit-parameters. Frequently, Java programmers define static members, perhaps `private`, as implementation aids for their instance members. These move to the companion, too; a common pattern is to import the companion object's members in the class, like so: - class X { - import X._ +``` +class X { + import X._ - def blah = foo - } + def blah = foo +} - object X { - private def foo = 42 - } +object X { + private def foo = 42 +} +``` This illustrates another feature: in the context of `private`, a class and its companion are friends. `object X` can access private members of `class X`, and vice versa. To make a member *really* private to one or the other, use `private[this]`. diff --git a/tutorials/tour/traits.md b/tutorials/tour/traits.md index 250a33c9e..7b5ad7304 100644 --- a/tutorials/tour/traits.md +++ b/tutorials/tour/traits.md @@ -13,31 +13,37 @@ tutorial-previous: classes Similar to interfaces in Java, traits are used to define object types by specifying the signature of the supported methods. Like in Java 8, Scala allows traits to be partially implemented; i.e. it is possible to define default implementations for some methods. In contrast to classes, traits may not have constructor parameters. Here is an example: - trait Similarity { - def isSimilar(x: Any): Boolean - def isNotSimilar(x: Any): Boolean = !isSimilar(x) - } +```tut +trait Similarity { + def isSimilar(x: Any): Boolean + def isNotSimilar(x: Any): Boolean = !isSimilar(x) +} +``` This trait consists of two methods `isSimilar` and `isNotSimilar`. While `isSimilar` does not provide a concrete method implementation (it is abstract in the terminology of Java), method `isNotSimilar` defines a concrete implementation. Consequently, classes that integrate this trait only have to provide a concrete implementation for `isSimilar`. The behavior for `isNotSimilar` gets inherited directly from the trait. Traits are typically integrated into a [class](classes.html) (or other traits) with a [mixin class composition](mixin-class-composition.html): - class Point(xc: Int, yc: Int) extends Similarity { - var x: Int = xc - var y: Int = yc - def isSimilar(obj: Any) = - obj.isInstanceOf[Point] && - obj.asInstanceOf[Point].x == x - } - object TraitsTest extends App { - val p1 = new Point(2, 3) - val p2 = new Point(2, 4) - val p3 = new Point(3, 3) - println(p1.isNotSimilar(p2)) - println(p1.isNotSimilar(p3)) - println(p1.isNotSimilar(2)) - } +```tut +class Point(xc: Int, yc: Int) extends Similarity { + var x: Int = xc + var y: Int = yc + def isSimilar(obj: Any) = + obj.isInstanceOf[Point] && + obj.asInstanceOf[Point].x == x +} +object TraitsTest extends App { + val p1 = new Point(2, 3) + val p2 = new Point(2, 4) + val p3 = new Point(3, 3) + println(p1.isNotSimilar(p2)) + println(p1.isNotSimilar(p3)) + println(p1.isNotSimilar(2)) +} +``` Here is the output of the program: - false - true - true +``` +false +true +true +``` diff --git a/tutorials/tour/unified-types.md b/tutorials/tour/unified-types.md index 323511941..5c4bff50a 100644 --- a/tutorials/tour/unified-types.md +++ b/tutorials/tour/unified-types.md @@ -20,25 +20,29 @@ The superclass of all classes `scala.Any` has two direct subclasses `scala.AnyVa Please note that the diagram above also shows implicit conversions between the value classes. Here is an example that demonstrates that both numbers, characters, boolean values, and functions are objects just like every other object: - object UnifiedTypes extends App { - val set = new scala.collection.mutable.LinkedHashSet[Any] - set += "This is a string" // add a string - set += 732 // add a number - set += 'c' // add a character - set += true // add a boolean value - set += main _ // add the main function - val iter: Iterator[Any] = set.iterator - while (iter.hasNext) { - println(iter.next.toString()) - } - } - +```tut +object UnifiedTypes extends App { + val set = new scala.collection.mutable.LinkedHashSet[Any] + set += "This is a string" // add a string + set += 732 // add a number + set += 'c' // add a character + set += true // add a boolean value + set += main _ // add the main function + val iter: Iterator[Any] = set.iterator + while (iter.hasNext) { + println(iter.next.toString()) + } +} +``` + The program declares an application `UnifiedTypes` in form of a top-level [singleton object](singleton-objects.html) extending `App`. The application defines a local variable `set` which refers to an instance of class `LinkedHashSet[Any]`. The program adds various elements to this set. The elements have to conform to the declared set element type `Any`. In the end, string representations of all elements are printed out. Here is the output of the program: - This is a string - 732 - c - true - +``` +This is a string +732 +c +true + +``` diff --git a/tutorials/tour/upper-type-bounds.md b/tutorials/tour/upper-type-bounds.md index 4b49a57f7..99d258984 100644 --- a/tutorials/tour/upper-type-bounds.md +++ b/tutorials/tour/upper-type-bounds.md @@ -13,23 +13,25 @@ tutorial-previous: variances In Scala, [type parameters](generic-classes.html) and [abstract types](abstract-types.html) may be constrained by a type bound. Such type bounds limit the concrete values of the type variables and possibly reveal more information about the members of such types. An _upper type bound_ `T <: A` declares that type variable `T` refers to a subtype of type `A`. Here is an example which relies on an upper type bound for the implementation of the polymorphic method `findSimilar`: - trait Similar { - def isSimilar(x: Any): Boolean - } - case class MyInt(x: Int) extends Similar { - def isSimilar(m: Any): Boolean = - m.isInstanceOf[MyInt] && - m.asInstanceOf[MyInt].x == x - } - object UpperBoundTest extends App { - def findSimilar[T <: Similar](e: T, xs: List[T]): Boolean = - if (xs.isEmpty) false - else if (e.isSimilar(xs.head)) true - else findSimilar[T](e, xs.tail) - val list: List[MyInt] = List(MyInt(1), MyInt(2), MyInt(3)) - println(findSimilar[MyInt](MyInt(4), list)) - println(findSimilar[MyInt](MyInt(2), list)) - } +```tut +trait Similar { + def isSimilar(x: Any): Boolean +} +case class MyInt(x: Int) extends Similar { + def isSimilar(m: Any): Boolean = + m.isInstanceOf[MyInt] && + m.asInstanceOf[MyInt].x == x +} +object UpperBoundTest extends App { + def findSimilar[T <: Similar](e: T, xs: List[T]): Boolean = + if (xs.isEmpty) false + else if (e.isSimilar(xs.head)) true + else findSimilar[T](e, xs.tail) + val list: List[MyInt] = List(MyInt(1), MyInt(2), MyInt(3)) + println(findSimilar[MyInt](MyInt(4), list)) + println(findSimilar[MyInt](MyInt(2), list)) +} +``` Without the upper type bound annotation it would not be possible to call method `isSimilar` in method `findSimilar`. The usage of lower type bounds is discussed [here](lower-type-bounds.html). diff --git a/tutorials/tour/variances.md b/tutorials/tour/variances.md index 431c9bd1d..73c98c992 100644 --- a/tutorials/tour/variances.md +++ b/tutorials/tour/variances.md @@ -14,24 +14,26 @@ Scala supports variance annotations of type parameters of [generic classes](gene In the page about [generic classes](generic-classes.html) an example for a mutable stack was given. We explained that the type defined by the class `Stack[T]` is subject to invariant subtyping regarding the type parameter. This can restrict the reuse of the class abstraction. We now derive a functional (i.e. immutable) implementation for stacks which does not have this restriction. Please note that this is an advanced example which combines the use of [polymorphic methods](polymorphic-methods.html), [lower type bounds](lower-type-bounds.html), and covariant type parameter annotations in a non-trivial fashion. Furthermore we make use of [inner classes](inner-classes.html) to chain the stack elements without explicit links. - class Stack[+A] { - def push[B >: A](elem: B): Stack[B] = new Stack[B] { - override def top: B = elem - override def pop: Stack[B] = Stack.this - override def toString() = elem.toString() + " " + - Stack.this.toString() - } - def top: A = sys.error("no element on stack") - def pop: Stack[A] = sys.error("no element on stack") - override def toString() = "" - } - - object VariancesTest extends App { - var s: Stack[Any] = new Stack().push("hello"); - s = s.push(new Object()) - s = s.push(7) - println(s) - } +```tut +class Stack[+A] { + def push[B >: A](elem: B): Stack[B] = new Stack[B] { + override def top: B = elem + override def pop: Stack[B] = Stack.this + override def toString() = elem.toString() + " " + + Stack.this.toString() + } + def top: A = sys.error("no element on stack") + def pop: Stack[A] = sys.error("no element on stack") + override def toString() = "" +} + +object VariancesTest extends App { + var s: Stack[Any] = new Stack().push("hello"); + s = s.push(new Object()) + s = s.push(7) + println(s) +} +``` The annotation `+T` declares type `T` to be used only in covariant positions. Similarly, `-T` would declare `T` to be used only in contravariant positions. For covariant type parameters we get a covariant subtype relationship regarding this type parameter. For our example this means `Stack[T]` is a subtype of `Stack[S]` if `T` is a subtype of `S`. The opposite holds for type parameters that are tagged with a `-`. diff --git a/tutorials/tour/xml-processing.md b/tutorials/tour/xml-processing.md index 96e842c37..a16a4359c 100644 --- a/tutorials/tour/xml-processing.md +++ b/tutorials/tour/xml-processing.md @@ -17,44 +17,50 @@ XML data is represented as labeled trees. Starting with Scala 1.2 (previous vers Consider the following XML document: - - - Hello XHTML world - - -

Hello world

-

Scala talks XHTML

- - +```html + + + Hello XHTML world + + +

Hello world

+

Scala talks XHTML

+ + +``` This document can be created by the following Scala program: - object XMLTest1 extends App { - val page = - - - Hello XHTML world - - -

Hello world

-

Scala talks XHTML

- - ; - println(page.toString()) - } +```tut +object XMLTest1 extends App { + val page = + + + Hello XHTML world + + +

Hello world

+

Scala talks XHTML

+ + ; + println(page.toString()) +} +``` It is possible to mix Scala expressions and XML: - object XMLTest2 extends App { - import scala.xml._ - val df = java.text.DateFormat.getDateInstance() - val dateString = df.format(new java.util.Date()) - def theDate(name: String) = - - Hello, { name }! Today is { dateString } - ; - println(theDate("John Doe").toString()) - } +```tut +object XMLTest2 extends App { + import scala.xml._ + val df = java.text.DateFormat.getDateInstance() + val dateString = df.format(new java.util.Date()) + def theDate(name: String) = + + Hello, { name }! Today is { dateString } + ; + println(theDate("John Doe").toString()) +} +``` ### Data Binding ### It many cases, you have a DTD for the XML documents you want to process. You will want to create special Scala classes for it, and some code to parse the XML, and to save. Scala comes with a nifty tool that turns your DTDs into a collection of Scala class definitions which do all of this for you. From 990085e5699577a5aaca7a43eabe04a1c12dbef1 Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Tue, 4 Oct 2016 11:18:50 +0200 Subject: [PATCH 4/9] add breaking change This is to demonstrate that Travis will catch tut errors. --- tutorials/tour/case-classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorials/tour/case-classes.md b/tutorials/tour/case-classes.md index bb732efd0..c7896f48a 100644 --- a/tutorials/tour/case-classes.md +++ b/tutorials/tour/case-classes.md @@ -32,7 +32,7 @@ Fun("x", Fun("y", App(Var("x"), Var("y")))) The constructor parameters of case classes are treated as public values and can be accessed directly. ```tut -val x = Var("x") +val x = x println(x.name) ``` From 622434073d4b539c9f79b58e3ec868cca13aa98d Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Tue, 4 Oct 2016 11:39:28 +0200 Subject: [PATCH 5/9] try to get travis to give exit status 1 for run-tut script --- .travis.yml | 1 + scripts/run-tut.sh | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ebab291c3..dc33b61f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,4 +12,5 @@ install: script: - ./scripts/run-tut.sh +- rm -r tut-tmp - bundle exec jekyll build diff --git a/scripts/run-tut.sh b/scripts/run-tut.sh index 2a3ee97ae..ad51ea626 100755 --- a/scripts/run-tut.sh +++ b/scripts/run-tut.sh @@ -4,4 +4,3 @@ COURSIER_CLASSPATH="$(./coursier fetch -p com.chuusai:shapeless_2.11:2.3.1 org.s ./coursier launch -r "https://dl.bintray.com/tpolecat/maven/" org.tpolecat:tut-core_2.11:0.4.4 -- . tut-tmp '.*\.md$' -classpath "$COURSIER_CLASSPATH" -rm -r tut-tmp From 3a052b61ca19409abb8081ad34aec8af412b76a1 Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Tue, 4 Oct 2016 11:50:56 +0200 Subject: [PATCH 6/9] fix breaking change. --- tutorials/tour/case-classes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorials/tour/case-classes.md b/tutorials/tour/case-classes.md index c7896f48a..bb732efd0 100644 --- a/tutorials/tour/case-classes.md +++ b/tutorials/tour/case-classes.md @@ -32,7 +32,7 @@ Fun("x", Fun("y", App(Var("x"), Var("y")))) The constructor parameters of case classes are treated as public values and can be accessed directly. ```tut -val x = x +val x = Var("x") println(x.name) ``` From 27782655ffea4722525e6d707ff346eb4ed51958 Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Tue, 4 Oct 2016 11:58:38 +0200 Subject: [PATCH 7/9] add a bit of documentation about tut --- contribute.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contribute.md b/contribute.md index e075804b8..63dff5fd9 100644 --- a/contribute.md +++ b/contribute.md @@ -39,6 +39,8 @@ It's statically generated from [Markdown](http://en.wikipedia.org/wiki/Markdown) The markdown syntax being used supports [Maruku](http://maruku.rubyforge.org/maruku.html) extensions, and has automatic syntax highlighting, without the need for any tags. +Additionally [tut](https://github.com/tpolecat/tut) is used during pull requests to valid Scala code blocks. To use this feature you must use the backtick notation as documented by tut. Note that only validation are done. The output files from tut are not used in the building of the tutorial. Either use `tut` or `tut:fail` for your code blocks. + ## Submitting Docs For one to contribute a document, one must simply From aab3b230aad31a765934f750e06f993e4b53e00f Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Wed, 5 Oct 2016 20:26:44 +0200 Subject: [PATCH 8/9] Update contribute.md two grammar changes --- contribute.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contribute.md b/contribute.md index 63dff5fd9..be5a765f7 100644 --- a/contribute.md +++ b/contribute.md @@ -39,7 +39,7 @@ It's statically generated from [Markdown](http://en.wikipedia.org/wiki/Markdown) The markdown syntax being used supports [Maruku](http://maruku.rubyforge.org/maruku.html) extensions, and has automatic syntax highlighting, without the need for any tags. -Additionally [tut](https://github.com/tpolecat/tut) is used during pull requests to valid Scala code blocks. To use this feature you must use the backtick notation as documented by tut. Note that only validation are done. The output files from tut are not used in the building of the tutorial. Either use `tut` or `tut:fail` for your code blocks. +Additionally [tut](https://github.com/tpolecat/tut) is used during pull requests to validate Scala code blocks. To use this feature you must use the backtick notation as documented by tut. Note that only validation is done. The output files from tut are not used in the building of the tutorial. Either use `tut` or `tut:fail` for your code blocks. ## Submitting Docs From d57f72182791df7291dc32d3f2d18c0b2be90acd Mon Sep 17 00:00:00 2001 From: Jarrod Brockman Date: Thu, 6 Oct 2016 10:24:04 +0200 Subject: [PATCH 9/9] update Gemfile to reflect current usage. https://help.github.com/articles/setting-up-your-github-pages-site-locally-with-jekyll/ https://github.com/github/pages-gem --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 053c27dc3..37f5eaa42 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,2 @@ source 'https://rubygems.org' -gem 'github-pages' +gem 'github-pages', group: :jekyll_plugins