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

# Background

## Types of functions

Almost everything in R is a function. There are several types of functions, the most familiar type is called using the _prefix_ form: 


```{r, eval = FALSE}
help("function")
```

There are also _infix_ operators, and these are also functions. You can call them also using the prefix form by enclosing the operator in backticks. 

```{r}
1 + 2
`+`(1, 2)
#help("+")
```

_Replacement_ functions assign values


```{r}
x <- 1
x

`<-`(x, 2)
x
```

_Special_ functions include things like indexing `[`, `[[`, and control flow `if` and `for`. 

An _anonymous_ function is a function that is defined inline, usually passed to another function, without assigning it a name. You may have used them in `lapply` and variants: 


```{r}
x <- list(1:3, 4:5)
lapply(x, function(z) z[2])
```

Now that you know that indexing is itself a function, can you perform the same operation without using an anonymous function? 

```{r}
lapply(x, `[`, 2)
```


## Finding and inspecting functions

The help file for a function can be found by calling `help` or using the `?` operator

```{r, eval = FALSE}
help("sample")
?sample
```

The body of a function can be printed to the console by typing the name of the function without parentheses: 

```{r}
sample
```

The `environment` field at the end of the function body tells you where the function lives, i.e., in what package. You can call functions by typing the package name, `::`, then the function name:

```{r}
base::sample
base::sample(1:10, 1)
```

## Function arguments

What are the arguments of the `sample` function? How can we find out? 

```{r}
#help(sample)
formals(sample)
args(sample)
str(sample)
```

Which arguments have default values? What are they? 

When you call a function, arguments are matched by: 

1. Exact name
2. Partial name
3. Position

in that order. The following calls are equivalent, which one is easiest to understand? 

```{r}
x <- 1:4

set.seed(123)
sample(x = x, size = 2, replace = FALSE)

set.seed(123)
sample(x, si = 2, rep = FALSE)

set.seed(123)
sample(replace = FALSE, size = 2, x = x)

set.seed(123)
sample(x, 2)
```

### Elipsis as a function argument

`...` is a possible function argument. It refers to an arbitrary list of expressions. Here are some possible uses: 

1. Passing arguments to other functions. If your function calls another function that may take arguments, they can be passed directly using `...` instead of listing the names of the arguments in your function. An example is `lapply`. Why is the `...` necessary in this case?

```{r}
formals(lapply)
```

Other examples are `c`, `rbind`, and `cbind`. Why do these functions use `...`? 

### Lazy evaluation

R does not evaluate function arguments until they are used in the function body, this is called _lazy evaluation_. This is why R does not check for missing arguments, an error won't occur until the argument is used in the function. 

```{r}
h01 <- function(x) {
    
    "Hello world!"
    
}

h01()
h01(stop("Error"))

```

One way to manually check for arguments is with `missing`: 


```{r}
h02 <- function(x) {
    
    if(missing(x)) {
        return("Missing x!")
    }
    "Hello world!"
    
}

h02()
h02(1)

```


## Intro to lexical scoping

An _environment_ can be thought of as a collection of objects. When you are working at the console, you are working in the _global enviroment_. You can view the names of objects in an environment with `ls`, which lists the objects in the current environment by default:

```{r}
ls()

hello <- "Hello world"

ls()
```


When a function is invoked, it is called inside its own environment that contains the arguments and things defined in the function body: 

```{r}
f01 <- function(y) {
    
    x <- 1
    ls()
    
}

f01("a")
```


The code in the function body does things with the objects, how does R find things, and in which environments does it look? This is the concept of lexical scoping. When a function is called, R follows simple rules to find things: 

1. Look in the current function environment first, that is the environment where the function was _defined_. 
2. If not found, look in the parent environment. 
3. Repeat 2 until there are no more parents. 
4. If not found, throw an error.


What do the following functions return? 

```{r}
x <- 1
f02 <- function(y = 2) {
    
    y + x
    
}

f02()

y <- 1
f03 <- function() {
    
    y <- 2
    i <- function() {
        
        z <- 3
        c(x, y, z)
    }
    
    i()
}


f03()

```





# Exercises

1. Define your own infix function that concatenates two strings. Can this operator be used to concatenate more than 2 strings? How does that work? Write the function call as prefix form to show how.

```{r}
`% %` <- function(a, b) {
    
    paste(a, b)
    
}

"my" % % "name"
"my" % % "name" % % "is" % % "Mike"

`% %`(`% %`(`% %`("my", "name"), "is"), "Mike")
```


2. Define your own replacement function that replaces the second element of a vector. 

```{r}
`second<-` <- function(x, value){
    
    x[2] <- value
    x
    
}

x <- 1:10
second(x) <- 11
x
```


2b. Make a more general function that replaces the _i_ th element of a vector. Illustrate how the replacement function works when composed. 

```{r}
`modify<-` <- function(x, i, value) {
    
    x[i] <- value
    x
    
}

x <- 1:10
modify(x, 2) <- modify(x, 1) <- 11
x

x <- 1:10
`modify<-`(`modify<-`(x, 2, 11), 1, 11)

```


3. Look at the function `sample`. What does sample do when `size` is not supplied? How would you rewrite this function to make it more clear to users that `size` is not necessary? 

