You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _overviews/scala3-book/control-structures.md
+176-1Lines changed: 176 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -16,10 +16,11 @@ Scala has the control structures you expect to find in a programming language, i
16
16
-`while` loops
17
17
-`try`/`catch`/`finally`
18
18
19
-
It also has two other powerful constructs that you may not have seen before, depending on your programming background:
19
+
It also has three other powerful constructs that you may not have seen before, depending on your programming background:
20
20
21
21
-`for` expressions (also known as _`for` comprehensions_)
22
22
-`match` expressions
23
+
-`boundary`/`break` expressions
23
24
24
25
These are all demonstrated in the following sections.
25
26
@@ -989,4 +990,178 @@ finally
989
990
990
991
Assuming that the `openAndReadAFile` method uses the Java `java.io.*` classes to read a file and doesn't catch its exceptions, attempting to open and read a file can result in both a `FileNotFoundException` and an `IOException`, and those two exceptions are caught in the `catch` block of this example.
991
992
993
+
## boundary/break
994
+
995
+
The `boundary`/`break` expression is used to exit a block of code while optionally returning a value.
996
+
For example, it can be used to break out of a nested loop:
997
+
998
+
{% tabs control-structures-32 %}
999
+
{% tab 'Scala 3 Only' %}
1000
+
1001
+
```scala
1002
+
importscala.util.boundary, boundary.break
1003
+
1004
+
valresult=
1005
+
boundary:
1006
+
for i <-1 to 10do
1007
+
for j <-1 to 10do
1008
+
if i ==7&& j ==9then break("found")
1009
+
"not found"
1010
+
1011
+
println(result)
1012
+
```
1013
+
1014
+
{% endtab %}
1015
+
{% endtabs %}
1016
+
1017
+
Since `break` uses an exception to control the execution flow, mixing it with `try`/`catch` can lead to unexpected results:
1018
+
1019
+
{% tabs control-structures-33 %}
1020
+
{% tab 'Scala 3 Only' %}
1021
+
1022
+
```scala
1023
+
importscala.util.boundary, boundary.break
1024
+
1025
+
valresult=boundary:
1026
+
try
1027
+
for i <-1 to 10do
1028
+
some_operation(i)
1029
+
if i ==5then break(i)
1030
+
catch
1031
+
casee: Exception=>-1
1032
+
1033
+
println(result) // prints -1, not 5
1034
+
```
1035
+
1036
+
{% endtab %}
1037
+
{% endtabs %}
1038
+
1039
+
The right way to use it would be to place the `boundary` expression inside the `try` block:
1040
+
1041
+
{% tabs control-structures-34 %}
1042
+
{% tab 'Scala 3 Only' %}
1043
+
1044
+
```scala
1045
+
importscala.util.boundary, boundary.break
1046
+
1047
+
valresult=
1048
+
try
1049
+
boundary:
1050
+
for i <-1 to 10do
1051
+
some_operation(i)
1052
+
if i ==5then break(i)
1053
+
catch
1054
+
casee: Exception=>-1
1055
+
1056
+
println(result) // 5
1057
+
```
1058
+
1059
+
{% endtab %}
1060
+
{% endtabs %}
1061
+
1062
+
## Custom control structures
1063
+
1064
+
The use of Scala 3 quiet syntax, by-name parameters, context parameters and `boundary`/`break` allows for writing code
1065
+
that resembles the built-in control structures and helps with reducing the boilerplate.
1066
+
In this example, the `repeat` function wraps a simple `for` loop, and the by-name `action` parameter will be executed `n`
1067
+
times for its side effects.
1068
+
1069
+
{% tabs control-structures-35 %}
1070
+
{% tab 'Scala 3 Only' %}
1071
+
1072
+
```scala
1073
+
defrepeat(n: Int)(action: =>Unit):Unit=
1074
+
for i <-1 to n do
1075
+
action
1076
+
1077
+
repeat(5):
1078
+
println("test")
1079
+
```
1080
+
1081
+
{% endtab %}
1082
+
{% endtabs %}
1083
+
1084
+
Here's an example that simulates a `do`-`while` loop by using `boundary`/`break`:
0 commit comments