Skip to content

Commit 0a5786b

Browse files
committed
Added more to tour
1 parent 9d085b2 commit 0a5786b

8 files changed

+247
-1
lines changed

tour/anonymous-function-syntax.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
layout: overview
3+
title: Anonymous Function Syntax
4+
---
5+
6+
Scala provides a relatively lightweight syntax for defining anonymous functions. The following expression creates a successor function for integers:
7+
8+
(x: Int) => x + 1
9+
10+
This is a shorthand for the following anonymous class definition:
11+
12+
new Function1[Int, Int] {
13+
def apply(x: Int): Int = x + 1
14+
}
15+
16+
It is also possible to define functions with multiple parameters:
17+
18+
(x: Int, y: Int) => "(" + x + ", " + y + ")"
19+
20+
or with no parameter:
21+
22+
() => { System.getProperty("user.dir") }
23+
24+
There is also a very lightweight way to write function types. Here are the types of the three functions defined above:
25+
26+
Int => Int
27+
(Int, Int) => String
28+
() => String
29+
30+
This syntax is a shorthand for the following types:
31+
32+
Function1[Int, Int]
33+
Function2[Int, Int, String]
34+
Function0[String]

tour/case-classes.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
layout: overview
3+
title: Case Classes
4+
---
5+
6+
Scala supports the notion of _case classes_. Case classes are regular classes which export their constructor parameters and which provide a recursive decomposition mechanism via [pattern matching](pattern-matching.html).
7+
8+
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`.
9+
10+
abstract class Term
11+
case class Var(name: String) extends Term
12+
case class Fun(arg: String, body: Term) extends Term
13+
case class App(f: Term, v: Term) extends Term
14+
15+
This class hierarchy can be used to represent terms of the [untyped lambda calculus](http://www.ezresult.com/article/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.
16+
17+
Here is an example:
18+
19+
Fun("x", Fun("y", App(Var("x"), Var("y"))))
20+
21+
The constructor parameters of case classes are treated as public values and can be accessed directly.
22+
23+
val x = Var("x")
24+
Console.println(x.name)
25+
26+
For every case class the Scala compiler generates equals method which implements structural equality and a `toString` method. For instance:
27+
28+
val x1 = Var("x")
29+
val x2 = Var("x")
30+
val y1 = Var("y")
31+
println("" + x1 + " == " + x2 + " => " + (x1 == x2))
32+
println("" + x1 + " == " + y1 + " => " + (x1 == y1))
33+
will print
34+
Var(x) == Var(x) => true
35+
Var(x) == Var(y) => false
36+
37+
It makes only sense to define case classes if pattern matching is used to decompose data structures. The following object defines a pretty printer function for our lambda calculus representation:
38+
39+
object TermTest extends Application {
40+
def printTerm(term: Term) {
41+
term match {
42+
case Var(n) =>
43+
print(n)
44+
case Fun(x, b) =>
45+
print("^" + x + ".")
46+
printTerm(b)
47+
case App(f, v) =>
48+
Console.print("(")
49+
printTerm(f)
50+
print(" ")
51+
printTerm(v)
52+
print(")")
53+
}
54+
}
55+
def isIdentityFun(term: Term): Boolean = term match {
56+
case Fun(x, Var(y)) if x == y => true
57+
case _ => false
58+
}
59+
val id = Fun("x", Var("x"))
60+
val t = Fun("x", Fun("y", App(Var("x"), Var("y"))))
61+
printTerm(t)
62+
println
63+
println(isIdentityFun(id))
64+
println(isIdentityFun(t))
65+
}
66+
67+
In our example, the function `print` is expressed as a pattern matching statement starting with the `match` keyword and consisting of sequences of `case Pattern => Body` clauses.
68+
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.

tour/currying.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
layout: overview
3+
title: Currying
4+
---
5+
6+
Methods may define multiple parameter lists. When a method is called with a fewer number of parameter lists, then this will yield a function taking the missing parameter lists as its arguments.
7+
8+
Here is an example:
9+
10+
object CurryTest extends Application {
11+
12+
def filter(xs: List[Int], p: Int => Boolean): List[Int] =
13+
if (xs.isEmpty) xs
14+
else if (p(xs.head)) xs.head :: filter(xs.tail, p)
15+
else filter(xs.tail, p)
16+
17+
def modN(n: Int)(x: Int) = ((x % n) == 0)
18+
19+
val nums = List(1, 2, 3, 4, 5, 6, 7, 8)
20+
println(filter(nums, modN(2)))
21+
println(filter(nums, modN(3)))
22+
}
23+
24+
_Note: method `modN` is partially applied in the two `filter` calls; i.e. only its first argument is actually applied. The `termmodN(2)` yields a function of type `Int => Boolean` and is thus a possible candidate for the second argument of function `filter`._
25+
26+
Here's the output of the program above:
27+
28+
List(2,4,6,8)
29+
List(3,6)

tour/extractor-objects.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
layout: overview
3+
title: Extractor Objects
4+
---
5+
6+
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. For instance, the following code defines an extractor object Twice.
7+
8+
object Twice {
9+
def apply(x: Int): Int = x * 2
10+
def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None
11+
}
12+
13+
object TwiceTest extends Application {
14+
val x = Twice(21)
15+
x match { case Twice(n) => Console.println(n) } // prints 21
16+
}
17+
There are two syntactic conventions at work here:
18+
19+
The pattern `case Twice(n)` will cause an invocation of `Twice.unapply`, which is used to match any even number; the return value of the `unapply` signals whether the argument has matched or not, and any sub-values that can be used for further matching. Here, the sub-value is `z/2`
20+
21+
The `apply` method is not necessary for pattern matching. It is only used to mimick a constructor. `val x = Twice(21)` expands to `val x = Twice.apply(21)`.
22+
23+
The return type of an `unapply` should be chosen as follows:
24+
* If it is just a test, return a `Boolean`. For instance `case even()`
25+
* If it returns a single sub-value of type T, return an `Option[T]`
26+
* If you want to return several sub-values `T1,...,Tn`, group them in an optional tuple `Option[(T1,...,Tn)]`.
27+
28+
Sometimes, the number of sub-values is fixed and we would like to return a sequence. For this reason, you can also define patterns through `unapplySeq`. The last sub-value type `Tn` has to be `Seq[S]`. This mechanism is used for instance in pattern `case List(x1, ..., xn)`.
29+
30+
Extractors can make code more maintainable. For details, read the paper ["Matching Objects with Patterns"](http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf) (see section 4) by Emir, Odersky and Williams (January 2007).

tour/higher-order-functions.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
layout: overview
3+
title: Higher-order Functions
4+
---
5+
6+
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`:
7+
8+
def apply(f: Int => String, v: Int) = f(v)
9+
10+
_Note: methods are automatically coerced to functions if the context requires this._
11+
12+
Here is another example:
13+
14+
class Decorator(left: String, right: String) {
15+
def layout[A](x: A) = left + x.toString() + right
16+
}
17+
18+
object FunTest extends Application {
19+
def apply(f: Int => String, v: Int) = f(v)
20+
val decorator = new Decorator("[", "]")
21+
println(apply(decorator.layout, 7))
22+
}
23+
24+
Execution yields the output:
25+
26+
[7]
27+
28+
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.

tour/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Scala is a modern multi-paradigm programming language designed to express common
99
Scala is a pure object-oriented language in the sense that [every value is an object](unified_types.html). Types and behavior of objects are described by [classes](classes.html) and [traits](traits.html). Classes are extended by subclassing and a flexible [mixin-based composition](mixin-class-composition.html) mechanism as a clean replacement for multiple inheritance.
1010

1111
## Scala is functional ##
12-
Scala is also a functional language in the sense that every function is a value. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. Scala's case classes and its built-in support for pattern matching model algebraic types used in many functional programming languages.
12+
Scala is also a functional language in the sense that [every function is a value](unified_types.html). Scala provides a [lightweight syntax](anonymous-function-syntax.html) for defining anonymous functions, it supports [higher-order functions](higher-order-functions.html), it allows functions to be [nested](nested-functions.html), and supports [currying](currying.html). Scala's [case classes](case-classes.html) and its built-in support for [pattern matching](pattern-matching.html) model algebraic types used in many functional programming languages.
1313

1414
Furthermore, Scala's notion of pattern matching naturally extends to the processing of XML data with the help of right-ignoring sequence patterns. In this context, sequence comprehensions are useful for formulating queries. These features make Scala ideal for developing applications like web services.
1515

tour/nested-functions.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
layout: overview
3+
title: Nested Functions
4+
---
5+
6+
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:
7+
8+
object FilterTest extends Application {
9+
def filter(xs: List[Int], threshold: Int) = {
10+
def process(ys: List[Int]): List[Int] =
11+
if (ys.isEmpty) ys
12+
else if (ys.head < threshold) ys.head :: process(ys.tail)
13+
else process(ys.tail)
14+
process(xs)
15+
}
16+
println(filter(List(1, 9, 2, 8, 3, 7, 4), 5))
17+
}
18+
19+
_Note: the nested function `process` refers to variable `threshold` defined in the outer scope as a parameter value of `filter`._
20+
21+
The output of this program is:
22+
23+
List(1,2,3,4)

tour/pattern-matching.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
layout: overview
3+
title: Pattern Matching
4+
---
5+
6+
Scala has a built-in general pattern matching mechanism. It allows to match on any sort of data with a first-match policy.
7+
Here is a small example which shows how to match against an integer value:
8+
9+
object MatchTest1 extends Application {
10+
def matchTest(x: Int): String = x match {
11+
case 1 => "one"
12+
case 2 => "two"
13+
case _ => "many"
14+
}
15+
println(matchTest(3))
16+
}
17+
18+
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.
19+
20+
Here is a second example which matches a value against patterns of different types:
21+
22+
object MatchTest2 extends Application {
23+
def matchTest(x: Any): Any = x match {
24+
case 1 => "one"
25+
case "two" => 2
26+
case y: Int => "scala.Int"
27+
}
28+
println(matchTest("two"))
29+
}
30+
31+
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.
32+
33+
Scala's pattern matching statement is most useful for matching on algebraic types expressed via [case classes](case-classes.html).
34+
Scala also allows the definition of patterns independently of case classes, using unapply methods in [extractor objects](extractor-objects.html).

0 commit comments

Comments
 (0)