---
title: "Programming<br>Control Structures in R"
author: "Keith VanderLinden<br>Calvin University"
output:
  xaringan::moon_reader:
    nature:
      titleSlideClass: ["left", "top"]
      highlightLines: true
      ratio: "16:9"      
---

```{r child = "../../resources/scripts/slide-setup.Rmd"}
```

```{r packages, echo = FALSE, warning = FALSE, message = FALSE}
library(tidyverse)
```

# Control Structures in R

Programming languages generally provide the following basic *control structures*:

- Sequence
- Selection
- Repetition

In addition, they also generally provide the ability to write new *functions*.

???
- These more advanced programming constructs are useful in more advanced data analysis.
- We've been pretty much using sequence only, but the other control structures have, on occasion, been implicit.

---
# Control Structures: Selection

Selection statements implement &ldquo;decisions&rdquo; in code. 

.pull-left[
Traditional `if-else` Statement
```{r}
x <- NA

if (is.na(x)) { 
  print("NA warning!")
} else { 
  print("All clear!")
  }
```
]
.pull-right[
`case` Function
```{r}
x <- NaN

case_when(
  is.nan(x) ~ "NaN warning!",
  is.na(x)  ~ "NA warning!",
  TRUE      ~ "All clear!"
  )
```
]

???
- There is an `ifelse` function as well (used by necessity in the hotel dataset), but the `case_when` is more general.
- We'll see an example of using the second form in the data cleansing lecture demos.

---
# Control Structures: Repetition

Repetition statements implement &ldquo;iteration&rdquo; in code. 

.pull-left[
Traditional `for` Loop
```{r}
my_numbers <- c(1, -2, 3)

for (x in my_numbers) {
  print(abs(x))
} 
```
]
.pull-right[
Implicit Vector Looping
```{r}
my_numbers <- c(1, -2, 3)

abs(my_numbers)
```
Explicit Mapping Function

```{r}
map_dbl(my_numbers, abs)
```
]

???
- R supports traditional `for` and `while` statements, but the *implicit* looping in the vector operation and the *explicit* looping of the map operator are more common.

---
# Writing Functions

Functions implement procedural *abstraction*.

.pull-left[
Function *Definition*
```{r}
my_xor <- function (x, y) {
  (x | y) & !(x & y)
}
```
]
.pull-right[
Function *Call(s)*
```{r}
my_xor(TRUE, FALSE)
```

```{r}
my_xor(TRUE, TRUE)
```
]

???
- The principle of *abstraction* allows us to ignore low-level details.
- Here, we bundle the details of the XOR function into a function. This allows us to:
  - Focus on the logical analysis at hand rather than on the low-level details of XOR. 
  - Call the XOR function many times, without repeating all the low-level details. 
- Function components:
  - Name: Choose a good one (e.g., not `xor`, which is already taken or `frodo`, which is unintelligible.)
  - Arguments (aka, parameters): Specify the "input" data needed to do the function's work.
  - Body: This is the code required to do function's work. It usually specifies a return value.

---
# Example: Data Cleansing Functions

.pull-left[
Numeric Cleansing
```{r}
remove_outliers <- function(value) {
  case_when(
    value < 0   ~ NA_real_,
    value > 10  ~ NA_real_,  
    TRUE        ~ value
  )
}

remove_outliers(c(1, -2, 3, 11))
```
]
.pull-right[
Character Cleansing
```{r}
remove_undefined <- function(value) {
  ifelse(
    value %in% c('undergraduate', 
                 'graduate'),
    value, NA)
}

remove_undefined(
  c("undergraduate", 
    "freshman", 
    "graduate", 
    "supersenior")
)
```
]

???
- These sample functions remove out-of-range values (numeric or string).

---
# Example: FizzBuzz

This code solves the classic [FizzBuzz problem](https://en.wikipedia.org/wiki/Fizz_buzz).
```{r}
play_fizzbuzz <- function(fbnums) {
  case_when(
    fbnums %% 15 == 0 ~ "FizzBuzz",
    fbnums %% 3 == 0 ~ "Fizz",
    fbnums %% 5 == 0 ~ "Buzz",
    TRUE ~ as.character(fbnums)
    )
}

play_fizzbuzz(1:25)
```

.footnote[See: https://en.wikipedia.org/wiki/Fizz_buzz]

???
- This demos all the control structures:
  - explicit sequence and selection
  - implicit repetition
  - function abstraction

References:
- https://towardsdatascience.com/how-to-solve-the-fizzbuzz-problem-in-r-c62e7e6c959a
