Skip to content

Commit 1af9198

Browse files
committed
Switch and recursion
1 parent eea0459 commit 1af9198

File tree

11 files changed

+326
-39
lines changed

11 files changed

+326
-39
lines changed

src/SUMMARY.md

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -538,15 +538,36 @@ Make them do one. -->
538538
- [Loop over items](./array_list/loop_over_items.md)
539539
- [Set an item](./array_list/set_an_item.md)
540540
- [Remove an item](./array_list/remove_an_item.md)
541-
<!--- [HashMap](./hash_map.md)
542-
- [Multi-Dimensional Arrays](./multi_dimensional_arrays.md)
543-
- [Iterable and Iterator](./iterable_and_iterator.md)
541+
544542
# Concepts II
545543
- [Hyrum's Law](./hyrums_law.md)
546544
- [Authority](./hyrums_law/authority.md)
547545
- [Validity](./hyrums_law/validity.md)
548546
- [Emergent Properties](./hyrums_law/emergent_properties.md)
549547
- [Importance](./hyrums_law/importance.md)
548+
549+
# Control Flow V
550+
551+
- [Switch III](./switch_iii.md)
552+
- [break](./switch_iii/break.md)
553+
- [fallthrough](./switch_iii/fallthrough.md)
554+
- [return](./switch_iii/return.md)
555+
- [default](./switch_iii/default.md)
556+
- [yield](./switch_iii/yield.md)
557+
- [Recursion](./recursion.md)
558+
- [Disclaimer](./recursion/disclaimer.md)
559+
- [Base Case](./recursion/base_case.md)
560+
- [Comparison to Delegation](./recursion/comparison_to_delegation.md)
561+
- [Comparison to Loops](./recursion/comparison_to_loops.md)
562+
- [Counting Down](./recursion/counting_down.md)
563+
- [Accumulators](./recursion/accumulators.md)
564+
- [Recurse Over a String](./recursion/recursing_over_strings.md)
565+
- [Recurse Over an Array](./recursion/recursing_over_arrays.md)
566+
567+
<!--- [HashMap](./hash_map.md)
568+
- [Multi-Dimensional Arrays](./multi_dimensional_arrays.md)
569+
- [Iterable and Iterator](./iterable_and_iterator.md)
570+
550571
- [Encapsulation](./encapsulation.md)
551572
- [Implementation Details](./encapsulation/implementation_details.md)
552573
- [Methods](./encapsulation/methods.md)
@@ -556,29 +577,15 @@ Make them do one. -->
556577
- [Leaky Abstractions](./encapsulation/leaky_abstractions.md)
557578
- [Information Hiding](./encapsulation/information_hiding.md)
558579
559-
# Control Flow V
580+
560581
- [Loops III](./loops_iii.md)
561582
- [For-each loops](./loops_iii/for_each_loops.md)
562583
- [Arrays]()
563584
- [Iterable]()
564585
- [ArrayList]()
565586
- [Concurrent Modifications](./loops_iii/concurrent_modifications.md)
566587
- [Reasons to go back]() <!--
567-
- [Switch III](./switch_iii.md)
568-
- [Fallthrough](./switch_iii/fallthrough.md)
569-
- [break](./switch_iii/break.md)
570-
- [default](./switch_iii/default.md)
571-
- [return](./switch_iii/return.md)
572-
- [yield](./switch_iii/yield.md)
573-
- [Recursion](./recursion.md)
574-
- [Disclaimer](./recursion/disclaimer.md)
575-
- [Base Case](./recursion/base_case.md)
576-
- [Comparison to Delegation](./recursion/comparison_to_delegation.md)
577-
- [Comparison to Loops](./recursion/comparison_to_loops.md)
578-
- [Counting Down](./recursion/counting_down.md)
579-
- [Accumulators](./recursion/accumulators.md)
580-
- [Recurse Over a String](./recursion/recursing_over_strings.md)
581-
- [Recurse Over an Array](./recursion/recursing_over_arrays.md)
588+
582589
583590
# Code Structure V
584591
- [Interface Extension](./interface_extension.md)

src/recursion/accumulators.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Main {
4646
}
4747

4848
int timesTwo(int x) {
49-
timesTwo(x, 0);
49+
return timesTwo(x, 0);
5050
}
5151

5252
void main() {

src/recursion/comparison_to_delegation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
A related technique to recursion is "delegation."
44

5-
This is when you have one method call a different airity
5+
This is when you have one method call a different arity
66
version of itself.
77

88
```java
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,27 @@
11
# Recurse Over an Array
2+
3+
To write a recursive function which acts over each element
4+
of an array, the technique is the same as with you need to do much the same task as with regular loops,
5+
just by having your "current index" be a parameter to the function.
6+
7+
```java
8+
class Main {
9+
void printEachTimesEight(int[] nums, int i) {
10+
if (i < nums.length) {
11+
System.out.println(nums[i] * 8);
12+
printEachTimesEight(nums, i + 1);
13+
}
14+
}
15+
16+
void printEachTimesEight(int[] nums) {
17+
printEachTimesEight(nums, 0);
18+
}
19+
20+
void main() {
21+
printEachTimesEight(new int[] { 1, 2, 3 });
22+
}
23+
}
24+
```
25+
26+
This same general technique can be used to loop over other sorts of collections, like `ArrayList`. In that
27+
case you would use `.get()` and `.size()` instead of `[]` and `.length`, but the concept is the same.

src/recursion/recursing_over_strings.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,25 @@
22

33
To write a recursive function which acts over each character
44
of a `String` you need to do much the same task as with regular loops,
5-
just by having your "current index" be a parameter to the
5+
just by having your "current index" be a parameter to the function.
6+
7+
```java
8+
class Main {
9+
void printEachUpperCase(String s, int i) {
10+
if (i < s.length()) {
11+
System.out.println(Character.toUpperCase(s.charAt(i)));
12+
printEachUpperCase(s, i + 1);
13+
}
14+
}
15+
16+
void printEachUpperCase(String s) {
17+
printEachUpperCase(s, 0);
18+
}
19+
20+
void main() {
21+
printEachUpperCase("hello");
22+
}
23+
}
24+
```
25+
26+
This overload with the index is an example of a function taking an accumulator.

src/switch_iii.md

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,25 @@ But, due to this history, there is another kind of switch that doesn't use arrow
88
and instead uses a colon (`:`).
99

1010
```java
11-
boolean shouldBeMainCharacter(String name) {
12-
switch (name) {
13-
case "Gohan":
14-
return true;
15-
case "Goku":
16-
default:
17-
return false;
11+
class Main {
12+
boolean shouldBeMainCharacter(String name) {
13+
switch (name) {
14+
case "Gohan":
15+
return true;
16+
case "Goku":
17+
default:
18+
return false;
19+
}
20+
}
21+
22+
void main() {
23+
System.out.println(
24+
shouldBeMainCharacter("Goku")
25+
);
1826
}
19-
}
20-
void main() {
21-
System.out.println(
22-
shouldBeMainCharacter("Goku")
23-
);
2427
}
2528
```
2629

2730
This "C-Style Switch" is important to learn chiefly because, for a long time,
2831
it was the only switch in Java. Therefore in your coding life you are very likely to
29-
run into it when reading old code.
30-
31-
It also might be uniquely useful for you once in a blue moon. Who knows.
32+
run into it.

src/switch_iii/break.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,78 @@
11
# break
2+
3+
After each case label in a C-style switch, you should write `break;`.[^cookout]
4+
5+
```java
6+
class Main {
7+
void main() {
8+
String name = "Piccolo";
9+
switch (name) {
10+
case "Squidward":
11+
System.out.println("Invited, but not coming.");
12+
break;
13+
14+
case "Piccolo":
15+
System.out.println("Coming to the cookout.");
16+
break;
17+
18+
case "Spider-Man":
19+
System.out.println("Not coming");
20+
break;
21+
}
22+
}
23+
}
24+
```
25+
26+
This is different from breaking out of a loop and won't break out of any surrounding loops.
27+
28+
```java
29+
class Main {
30+
void main() {
31+
for (int i = 0; i < 3; i++) {
32+
// Will still run 3 times
33+
String name = "Piccolo";
34+
switch (name) {
35+
case "Squidward":
36+
System.out.println("Invited, but not coming.");
37+
break;
38+
39+
case "Piccolo":
40+
System.out.println("Coming to the cookout.");
41+
break;
42+
43+
case "Spider-Man":
44+
System.out.println("Not coming");
45+
break;
46+
}
47+
}
48+
}
49+
}
50+
```
51+
52+
To break out of surrounding loops you can use a labeled break.
53+
54+
```java
55+
class Main {
56+
void main() {
57+
outerLoop:
58+
for (int i = 0; i < 3; i++) {
59+
String name = "Piccolo";
60+
switch (name) {
61+
case "Squidward":
62+
System.out.println("Invited, but not coming.");
63+
break;
64+
65+
case "Piccolo":
66+
System.out.println("Coming to the cookout.");
67+
break outerLoop; // Will break out of the loop
68+
69+
case "Spider-Man":
70+
System.out.println("Not coming");
71+
break;
72+
}
73+
}
74+
}
75+
}
76+
```
77+
78+
[^cookout]: [Who should be invited to the cookout?](https://www.youtube.com/watch?v=64SoFWJHSd8)

src/switch_iii/default.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,65 @@
11
# default
2+
3+
Just like with normal switches, C-style switches can have a `default` label
4+
that matches when no other label does.
5+
6+
```java
7+
class Main {
8+
boolean shouldBeMainCharacter(String name) {
9+
switch (name) {
10+
case "Gohan":
11+
return true;
12+
default:
13+
return false;
14+
}
15+
}
16+
17+
void main() {
18+
System.out.println(
19+
shouldBeMainCharacter("Goku")
20+
);
21+
}
22+
}
23+
```
24+
25+
If you have a C-style switch over an enum you need this `default` case for exhaustiveness. Java does not
26+
otherwise accept that you have covered all the cases.
27+
28+
```java,does_not_compile
29+
enum Technique {
30+
KAMEHAMEHA,
31+
INSTANT_TRANSMISSION,
32+
KAIOKEN,
33+
ULTRA_INSTINCT
34+
}
35+
36+
class Main {
37+
boolean didGokuStealItFromSomeoneElse(Technique technique) {
38+
switch (technique) {
39+
case KAMEHAMEHA:
40+
System.out.println("Master Roshi Taught it to him");
41+
return true;
42+
case INSTANT_TRANSMISSION:
43+
System.out.println("Space aliens");
44+
return true;
45+
case KAIOKEN:
46+
System.out.println("King Kai's name is in it!");
47+
return true;
48+
case ULTRA_INSTINCT:
49+
System.out.println("I'd say not");
50+
return false;
51+
// Even though we covered every option, Java doesn't trust us.
52+
// You need a default label or to return later in the function
53+
//
54+
// default:
55+
// throw new IllegalStateException("Unexpected: " + technique);
56+
}
57+
}
58+
59+
void main() {
60+
System.out.println(
61+
didGokuStealItFromSomeoneElse(Technique.INSTANT_TRANSMISSION)
62+
);
63+
}
64+
}
65+
```

src/switch_iii/fallthrough.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,31 @@
11
# Fallthrough
22

3-
If the code for a given label does not `break`
4-
or `return` then
3+
If the code for a given label does not have a `break` then it will "fall through"
4+
to the cases below.
5+
6+
This is what makes C-style switches strange. It can occasionaly be useful if the same code should
7+
run for some or all cases.[^history]
8+
9+
```java
10+
class Main {
11+
void sayWhoTheyFought(String name) {
12+
switch (name) {
13+
case "Goku":
14+
System.out.println("Fought Pilaf");
15+
System.out.println("Fought The Red Ribbon Army");
16+
case "Gohan": // "Goku" will fall through to this case
17+
System.out.println("Fought Frieza");
18+
System.out.println("Fought Cell");
19+
System.out.println("Fought Majin Buu");
20+
}
21+
}
22+
23+
void main() {
24+
sayWhoTheyFought("Gohan");
25+
System.out.println("----------------------");
26+
sayWhoTheyFought("Goku");
27+
}
28+
}
29+
```
30+
31+
[^history]: [This StackExchange Post](https://softwareengineering.stackexchange.com/questions/162615/why-dont-languages-use-explicit-fall-through-on-switch-statements) explains how this came about. I don't have a primary source on the "The reason that C did it that way is that the creators of C intended switch statements to be easy to optimize into a jump table." claim, but it lines up with my biases and preconceptions. Therefore it must be true!

0 commit comments

Comments
 (0)