Skip to content

Commit d9106dd

Browse files
committed
Start writing the LexicalScopes section
1 parent 554f908 commit d9106dd

File tree

3 files changed

+166
-10
lines changed

3 files changed

+166
-10
lines changed

src/main/scala/scalatutorial/sections/DefinitionsAndEvaluation.scala

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,19 @@ object DefinitionsAndEvaluation extends ScalaTutorialSection {
4646
* = Methods =
4747
*
4848
* Definitions can have parameters. For instance:
49-
*
50-
* {{{
51-
* def square(x: Double) = x * x
52-
* }}}
53-
*
54-
* And then you can ''call'' a method as follows:
5549
*/
5650
def usingSquare(res0: Double): Unit = {
51+
def square(x: Double) = x * x
52+
5753
square(3.0) shouldBe res0
5854
}
5955

6056
/**
6157
* Let’s define a method that computes the area of a disc, given its radius:
6258
*/
6359
def areaExercise(res0: Double): Unit = {
60+
def square(x: Double) = x * x
61+
6462
def area(radius: Double): Double = 3.14159 * square(radius)
6563

6664
area(10) shouldBe res0
@@ -209,6 +207,4 @@ object DefinitionsAndEvaluation extends ScalaTutorialSection {
209207
*/
210208
def nothing(): Unit = ()
211209

212-
def square(x: Double) = x * x
213-
214210
}

src/main/scala/scalatutorial/sections/FunctionalLoops.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ object FunctionalLoops extends ScalaTutorialSection {
6868
*
6969
* To compute `sqrt(x)`:
7070
*
71-
* - Start with an initial _estimate_ `y` (let's pick `y = 1`).
71+
* - Start with an initial ''estimate'' `y` (let's pick `y = 1`).
7272
* - Repeatedly improve the estimate by taking the mean of `y` and `x/y`.
7373
*
7474
* Example:
@@ -83,7 +83,7 @@ object FunctionalLoops extends ScalaTutorialSection {
8383
*
8484
* = Implementation in Scala =
8585
*
86-
* First, we define a method which computes one iteration step
86+
* First, we define a method which computes one iteration step:
8787
*
8888
* {{{
8989
* def sqrtIter(guess: Double, x: Double): Double =

src/main/scala/scalatutorial/sections/LexicalScopes.scala

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,167 @@ package scalatutorial.sections
44
object LexicalScopes extends ScalaTutorialSection {
55

66
/**
7+
* = Nested functions =
78
*
9+
* It's good functional programming style to split up a task into many small functions.
10+
*
11+
* But the names of functions like `sqrtIter`, `improve`, and `isGoodEnough` (defined in the
12+
* previous section) matter only for the ''implementation'' of `sqrt`, not for its ''usage''.
13+
*
14+
* Normally we would not like users to access these functions directly.
15+
*
16+
* We can achieve this and at the same time avoid “name-space pollution” by
17+
* putting the auxiliary functions inside `sqrt`.
18+
*
19+
* = The `sqrt` Function, Take 2 =
20+
*
21+
* {{{
22+
* def sqrt(x: Double) = {
23+
* def sqrtIter(guess: Double, x: Double): Double =
24+
* if (isGoodEnough(guess, x)) guess
25+
* else sqrtIter(improve(guess, x), x)
26+
*
27+
* def improve(guess: Double, x: Double) =
28+
* (guess + x / guess) / 2
29+
*
30+
* def isGoodEnough(guess: Double, x: Double) =
31+
* abs(square(guess) - x) < 0.001
32+
*
33+
* sqrtIter(1.0, x)
34+
* }
35+
* }}}
36+
*
37+
* = Blocks in Scala =
38+
*
39+
* - A block is delimited by braces `{ ... }`.
40+
*
41+
* {{{
42+
* {
43+
* val x = f(3)
44+
* x * x
45+
* }
46+
* }}}
47+
*
48+
* - It contains a sequence of definitions or expressions.
49+
* - The last element of a block is an expression that defines its value.
50+
* - This return expression can be preceded by auxiliary definitions.
51+
* - Blocks are themselves expressions; a block may appear everywhere an expression can.
52+
*
53+
* = Blocks and Visibility =
54+
*
55+
* - The definitions inside a block are only visible from within the block.
56+
* - The definitions inside a block ''shadow'' definitions of the same names
57+
* outside the block.
58+
*
59+
* == Exercise: Scope Rules ==
60+
*
61+
* What is the value of `result` in the following program?
62+
*
63+
*/
64+
def scopeRules(res0: Int): Unit = {
65+
val x = 0
66+
def f(y: Int) = y + 1
67+
val result = {
68+
val x = f(3)
69+
x * x
70+
} + x
71+
result shouldBe res0
72+
}
73+
74+
/**
75+
* = Lexical Scoping =
76+
*
77+
* Definitions of outer blocks are visible inside a block unless they are shadowed.
78+
*
79+
* Therefore, we can simplify `sqrt` by eliminating redundant occurrences of the `x` parameter, which means
80+
* everywhere the same thing:
81+
*
82+
* = The `sqrt` Function, Take 3 =
83+
*
84+
* {{{
85+
* def sqrt(x: Double) = {
86+
* def sqrtIter(guess: Double): Double =
87+
* if (isGoodEnough(guess)) guess
88+
* else sqrtIter(improve(guess))
89+
*
90+
* def improve(guess: Double) =
91+
* (guess + x / guess) / 2
92+
*
93+
* def isGoodEnough(guess: Double) =
94+
* abs(square(guess) - x) < 0.001
95+
*
96+
* sqrtIter(1.0)
97+
* }
98+
* }}}
99+
*
100+
* = Semicolons =
101+
*
102+
* In Scala, semicolons at the end of lines are in most cases optional.
103+
*
104+
* You could write:
105+
*
106+
* {{{
107+
* val x = 1;
108+
* }}}
109+
*
110+
* but most people would omit the semicolon.
111+
*
112+
* On the other hand, if there are more than one statements on a line, they need to be
113+
* separated by semicolons:
114+
*
115+
* {{{
116+
* val y = x + 1; y * y
117+
* }}}
118+
*
119+
* = Semicolons and infix operators =
120+
*
121+
* One issue with Scala's semicolon convention is how to write expressions that span
122+
* several lines. For instance:
123+
*
124+
* {{{
125+
* someLongExpression
126+
* + someOtherExpression
127+
* }}}
128+
*
129+
* would be interpreted as ''two'' expressions:
130+
*
131+
* {{{
132+
* someLongExpression;
133+
* + someOtherExpression
134+
* }}}
135+
*
136+
* There are two ways to overcome this problem.
137+
*
138+
* You could write the multi-line expression in parentheses, because semicolons
139+
* are never inserted inside `(...)`:
140+
*
141+
* {{{
142+
* (someLongExpression
143+
* + someOtherExpression)
144+
* }}}
145+
*
146+
* Or you could write the operator on the first line, because this tells the Scala
147+
* compiler that the expression is not yet finished:
148+
*
149+
* {{{
150+
* someLongExpression +
151+
* someOtherExpression
152+
* }}}
153+
*
154+
* = Summary =
155+
*
156+
* You have seen simple elements of functional programing in Scala.
157+
*
158+
* - arithmetic and boolean expressions
159+
* - conditional expressions if-else
160+
* - functions with recursion
161+
* - nesting and lexical scope
162+
*
163+
* You have learned the difference between the call-by-name and
164+
* call-by-value evaluation strategies.
165+
*
166+
* You have learned a way to reason about program execution: reduce expressions using
167+
* the substitution model.
8168
*/
9169
def nothing(): Unit = ()
10170
}

0 commit comments

Comments
 (0)