@@ -4,7 +4,167 @@ package scalatutorial.sections
44object 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