```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

---

### R fundamentals 04: Elements of programming and basic debugging skills  
### (`r format(Sys.Date(), "%b %d, %y")`)

---

As the last part of R fundamentals series, we will study elements of R programming

---

#### Conditional statements and operators in R

<br>

R provides syntax to evaluate conditions. 

```{r eval=FALSE}
  if (condition) {
    expression
  }
```

As an example,

```{r eval=TRUE}
  # Assign x to -8
  x <- -8
  # Print if x is negative
  if (x < 0) {
    print("x is a negative number")
  }
```


----

<span style="color:blue">**Classwork/Homework**</span>: Change x to 5 and re-run the above code. What does that print?

---

<br>

`if...else` statements are evaluated thus:

```{r eval=FALSE}
  if (condition) {
    expression 1
  } else {
    expression 2
  }
```


----

<span style="color:blue">**Classwork/Homework**</span>: Repeat the previous classwork, this time adding an _else statement_ that prints "x is positive or zero", when needed.

---

<br>

We can also make `else if` statements as follows:


```{r eval=FALSE}
  if (condition 1) {
    expression
  } else if (condition 2) {
    expression
  } else {
    expression
  }
```

<br>

R provides logical operators:

* AND with symbol&nbsp;&nbsp;&nbsp;`&`
* OR with symbol&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`|`
* NOT with symbol&nbsp;&nbsp;&nbsp;`!`

<br>

The **AND** truth table

```{r eval=FALSE}
  # AND truth table
  TRUE  & TRUE   : TRUE
  TRUE  & FALSE  : FALSE
  FALSE & TRUE   : FALSE
  FALSE & FALSE  : FALSE
```

Example: `x <- 5` and `(x >3) & (x <8)` will evaluate to `TRUE`.


The **OR** truth table

```{r eval=FALSE}
  # OR truth table
  TRUE  | TRUE   : TRUE
  TRUE  | FALSE  : TRUE
  FALSE | TRUE   : TRUE
  FALSE | FALSE  : FALSE
```

Example: `x <- 5` and `(x >5) | (x <8)` will evaluate to `FALSE`.

The **NOT** truth table

```{r eval=FALSE}
  # NOT truth table
  !TRUE  : FALSE
  !FALSE : TRUE
```

Example:  `x <- 5` and `!((x >5) | (x <8))` will evaluate to `TRUE`.


----

<span style="color:blue">**Classwork/Homework**</span>: Create an R script that returns the max value of a vector `x` with length 3. Don’t use the aid of an auxiliary variable.

---

<br>

**Note**: R comes out of the _if statement_ as soon as the condition is met. It will **not** evaluate further conditions down the line even if they satisfy.

```{r eval=TRUE}
  # Assign x to 6
  x <- 6
  # Check if x is divisible by 2 or 3, if so print it is
  # Otherwise print it is not
  if (x %% 2 == 0) {
    print("x is divisible by 2")
  } else if(x %% 3 == 0) {
    print("x is divisible by 3")
  } else {
    print("x is neither divisible by 2 nor 3")
  }
```

<br>

We can apply logical operators on vectors and matrices - works element wise:

`c(TRUE,TRUE,FALSE) & c(FALSE,TRUE,TRUE)` will evaluate to `FALSE TRUE FALSE`.

`c(TRUE,TRUE,FALSE) | c(FALSE,TRUE,TRUE)` will evaluate to `TRUE TRUE TRUE`.

Also, we have `&&` and `||` operators in R. The difference between single `&`and `&&`is that, `&&` will only look at the first elements of the vectors. Similarly for `||`. Thus,

`c(TRUE,TRUE,FALSE) && c(FALSE,TRUE,TRUE)` will evaluate to `FALSE` and 

`c(TRUE,TRUE,FALSE) | c(FALSE,TRUE,TRUE)` will evaluate to `TRUE`.

We can check two objects are equal by the `==` sign or inequality using `!=` operator. 

```{r eval=TRUE}
  # Check the quality of logical objects
  TRUE == TRUE
  # Check the quality of logical objects
  TRUE == FALSE
  # Compare strings
  "hi" == "hello"
  # Or numbers
  2 == 2
  # Check inequlaity
  2 != 3
```

In fact, we can use comparison operators for objects!

```{r eval=TRUE}
  # Use comparison on objects
  "hello" >= "goodbye"
  # How about on logicals?
  TRUE < FALSE
```

Why is the comparison `TRUE < FALSE` evaluates to `FALSE` despite the fact that `T < F` in R? Becuase logicals are _coerced_. `TRUE` coresponds to 1 and `FALSE` to 0. We can also use comparison operators on vectors.

<br>

Here are two other useful functions to evaluate logical vectors: `any()` and `all()`.

`any()` is comparable to OR;  
it is enough that there is one TRUE to return TRUE  
`all()` is comparable to AND;  
it is enough that there is one FALSE to return FALSE  

The inclusion operator `%in%` , search for an element within a vector:
```{r, collapse=T}
# Here we have a list (a vector) of all sort of complex bacterial famalies 
bacFamVec <- c("Cyclobacteriaceae", "Leuconostocaceae", 
               "Leptotrichiaceae", "Pirellulaceae",
               "Rhizobiaceae", "Methylobacteriaceae", 
               "Mycobacteriaceae", "Staphylococcaceae" )

# Does the "Clostridiaceae" one of them?
( "Clostridiaceae" %in% bacFamVec )
```

##

----

<span style="color:blue">**Classwork/Homework**</span>: 

1. Compare two vectors of equal length and output the result.
2. How about vectors of unequal length? Why does the result makes sense?
3. Compare two matrices and lists and explain how R handles such comparisons.
4. Explore further the example of the "inclusion operator", does it matter if you reverse the order of the compared elements? If yes, what the difference is? 

---

<br>

#### Functions and data structures in R

The general syntax of a function:

```{r eval=FALSE}
  
  my_function <- function(arg 1, arg 2) {
    <body of the function>
  }
```

Unlike some other languages, in R, there is no special syntax for naming a function. One just defines like any other vector. 

Consider a simple function,

```{r eval=FALSE}
  # The add function
  add <- function(x, y=1) {
    x+y
  }
```

If y is not given any value, it will take the default argument. There is no difference between the functions we define and R supplied functions. There are three components for every function, the **formal**, the **body** and the **environment**.

```{r eval=TRUE}
  # The add function
  add <- function(x, y=1) {
    x+y
  }
  
  # Print the formals arguments
  formals(add)
  # Print the body 
  body(add)
  # Print the environment
  environment(add)
```

Environment is typically invisible, but it is important on how the function behaves. We will soon see scope for functions. In this case the environment is the global environment.


---

<span style="color:blue">**Classwork/Homework**</span>: What does this function do?

```{r eval=FALSE}
  f <- function(x) {
          if (x<0) {
              -x
          } else {
               x
            }
        }
```

---

<br>


Functions are just objects in R and act like any other object. You can assign a function to any other object and the object will behave exactly like the assigned function. Function need not have any name - they are called anonymous functions. Anonymous functions has to be called in one line. For example, `(function (x) {x+1})(2)` is an increment function that will produce the output 3.  

<br>
  
##### Scoping

R looks into the function scope for values.

```{r eval=TRUE}
  # Assign the value 10 for x
  x <- 10
  # Define a function f that returns a vector
  f <- function() {
    x <- 1
    y <- 3
    c(x,y)
  }
  # Print the function
  f()
```

If the value is not in the scope, it looks one level above.

```{r eval=TRUE}
  # Assign the value 10 for x
  x <- 10
  # Define a function f that returns a vector
  f <- function() {
    y <- 3
    c(x,y)
  }
  # Print the function 
  # Note x is not in the scope
  f()
```


----

<span style="color:blue">**Classwork/Homework**</span>: Use `rm(x)` in the above code to remove x from the global environment and report what happens when you call the function.

---

<br>

Scoping defines _where_ and not _when_ to look for a function. 

```{r eval=TRUE}
  # Define a function
  f <- function() x
  x <- 15
  f()
  x <- 20
  f()
```


This is a highly undersirable behaviour. So always as a practice design functions using the variables you'll use and not leave it to the environment. 

Lookup works the same for functions when it comes to scoping.

```{r eval=TRUE}
  # Define a function l
  l <- function(x) x + 20
  # Define another function and define l inside f
  f <- function() {
        l <- function(x) x +15
        l(20)
  }
  f()

```

If you use name like a function, R ignores any non-function objects when it looks it up. Here is an example:

```{r eval=TRUE}
  # Define c
  c <- 20
  # Use c as a combine 
  # R ignores the function aspect of c
  c(c=c)
```

Each call to a function has its own clean environment.

```{r eval=TRUE}
  # Define a function
  f <- function() {
    if (!exists("a")) {
      a <- 10
    } else {
      a <- a + 1
    }
    print(a)
  }
 f()
```


The environment of a function is cleared at the end of each call.
By default, function returns to the calling environment the value of the variable referred last.
Therefore, every call of this function is going to print only 10!

----

<span style="color:blue">**Classwork/Homework**</span> How do we get to advance **a** in **1** at each call?

---

<br>

##### A note on the NULL value 

Another important object in R is the `NULL` that specifies the absence of elements in a data structure.

Every data structure has two key properties. The `typeof()` function that specifies the type of the data structure and `length()` function that gives the length of the data structure.

Let's use it to compare `NULL` with `NA` that specifies the absense of values in a data structure. This can be seen as follows:

```{r eveal=TRUE}
  # Find the type and length of NULL
  typeof(NULL)
  length(NULL)
  # Find the type and length of NA
  typeof(NA)
  length(NA)
```

**Quiz**: How do you test for `NA` in a vector?

In fact there are many types of `NA` depending on the data type, one for each atomic type (like `NA` for integer etc.). Missing values are contagious - any mathematical operation involving `NA` will result in NA. Any logical comparison involving `NA` will result in `NA` too (like `NA == NA`).


---

#### Selected materials and references

* [An Introduction to R (pg. 40)](https://cran.r-project.org/doc/manuals/R-intro.pdf)
