---
title: "Curso básico de R: <br> Funciones"
author: "Francesc Carmona <br> fcarmona@ub.edu"
date: "15 de octubre de 2022"
output: 
  slidy_presentation:
  slide_level: 2
toc: TRUE
toc_depth: 2
number_sections: true
includes:
  before_body: header.html
---
  
  ```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

<br><br><br>
  
  El objetivo principal de este curso es proporcionar los elementos
básicos para empezar a trabajar con el lenguaje de programación R
en el ámbito de la Estadística.

Este curso está basado muy especialmente en el documento
*Introducción al uso y programación del sistema estadístico
R* <br> de Ramón Díaz-Uriarte de la Unidad de Bioinformática del
CNIO.

## Funciones

### Definición

- R es un lenguaje de programación que permite crear nuevas funciones.
- Una función se define con una asignación de la forma
```{r}
nombre <- function(arg1, arg2, ...){expresión}
```
- La expresión es una instrucción o grupo de instrucciones
    que utilizan los argumentos para calcular su valor.
- El valor de dicha expresión es el valor que proporciona
    R en su salida y éste puede ser un simple número, un vector,
    una gráfica, una lista o un mensaje.
- Ejemplo: Suma de una progresión aritmética
```{r}
suma <- function(a1,d,n){
               an <- a1+(n-1)*d
               ((a1+an)*n)/2
               }
```

### Plantilla básica

La plantilla básica de una función es

```{r eval=FALSE}
function_name <- function(function_arguments) { 
  function_body
  function_return_value
}
```

Cada uno de ellos es importante.

### El nombre

El nombre de la función puede ser casi cualquier cosa, incluso funciones o variables definidas previamente, así que tenga cuidado. Una vez que haya dado el nombre, puede usarlo como cualquier otra función, con paréntesis. Por ejemplo, para definir una función de desviación estándar usando la función <font color="green">`var()`</font>, podemos hacer
```{r}
std <- function(x) sqrt(var(x))
```

Se puede llamar sin paréntesis y así se obtiene la definición misma
```{r}
std
```

### Argumentos

- Una función sin argumentos.
```{r}
hello.world <- function() print("hello world") 
hello.world()
```

- Una función con un argumento.
```{r}
hello.someone <- function(name) print(paste("hello", name)) 
hello.someone("fred")
```

- Un argumento por defecto.

Si la función <font color="green">`hello.someone()`</font> anterior se utiliza sin valor para el argumento, da error. 
```{r eval=FALSE}
hello.someone()
```

Para corregir esta situación podemos dar un valor por defecto.
```{r}
hello.someone <- function(name="world") print(paste("hello ",name))
hello.someone()
```

La expresión <font color="green">`name="world"`</font> no es una asignación. 

### Argumentos (2)

- Una función con cuatro argumentos
```{r eval=FALSE}
una.f <- function(a, b, c = 4, d = FALSE){x1 <- a*z ...}
```
- Cuando llamamos a una función, los argumentos deben darse en el orden establecido o, si los nombramos, podemos darlos en cualquier orden:
```{r eval=FALSE}
una.f(4, 5)
una.f(b = 5, a = 4)
```
- Pero los argumentos que nombramos siempre se tienen que dar
    después de los posicionales:
```{r eval=FALSE}
una.f(c = 25, 4, 5) # error
```
- Los argumentos <font color="green">`c`</font> y <font color="green">`d`</font> tienen valores por defecto.
- Podemos especificarlos nosotros o no (i.e., usar los valores por defecto).

- <font color="green">`args(nombre.funcion)`</font> nos muestra los argumentos de cualquier función.
- "<font color="green">`...`</font>" permite pasar argumentos a otra función:
```{r eval=FALSE}
f3 <- function(x, y, label = "la x", ...){
                    plot(x, y, xlab = label, ...)
                    }
  
f3(1:5, 1:5)
f3(1:5, 1:5, col = "red")
```

- Para aplicar funciones a dos variables se puede utilizar
    el comando <font color="green">`outer()`</font>. Por ejemplo:
```{r eval=FALSE}
f <- function(x, y){cos(y)/(x^2-3)}
z <- outer(x, y, f)
```

### Cuerpo de la función y valor de retorno

- El cuerpo de la función y su valor devuelto hacen el trabajo de la función. El valor que se devuelve es lo último que se evalúa. Entonces, si solo se calcula una cosa, es fácil escribir una función.

- Si la función es más complicada, entonces el cuerpo de la función y el valor devuelto están encerrados en llaves: `{}`.

### Scope

- En el cuerpo, la función puede usar variables. Por lo general, estos son argumentos de la función. ¿Y si no lo son? Entonces R sale a cazar para ver qué encuentra. 

- En la función <font color="green">`una.f()`</font> "<font color="green">`z`</font>" es una *free variable*: ¿cómo se especifica su valor? 
- **Lexical scoping**
- Ver documento
    *Frames, environments and scope in R and S-PLUS* de J. Fox en
    [](https://socialsciences.mcmaster.ca/jfox/Books/Companion-1E/appendix.html)
    y sección 10.7 en *An introduction to R*.
- También ver <font color="green">`demo(scoping)`</font>.
```{r}
cubo <- function(n){
          sq <- function() n*n # aquí n no es un argumento
          n*sq()
          }
```

### Control de ejecución

- Principales instrucciones
```{r eval=FALSE}
if(cond) expr
if(cond) cons.expr  else  alt.expr
for(var in seq) expr
while(cond) expr
repeat expr
break
next
```
- La expresión <font color="green">`expr`</font> 
(también <font color="green">`alt.expr`</font>)
    puede ser una expresión simple o una de las llamadas
    expresiones compuestas, normalmente del tipo 
    <font color="green">`{expr1; expr2}`</font>.
- Uno de los errores más habituales es el olvido de los corchetes
    <font color="green">`{...}`</font> alrededor de las instrucciones, 
    i.e. después de <font color="green">`if(...)`</font>
    o <font color="green">`for(...)`</font>.
- <font color="green">`if (cond.logica)`</font> *instrucción* <font color="green">`else`</font>
    *instrucción.alternativa*
```{r}
f4 <- function(x){
         if(x > 5) print("x > 5")
         else {
           y <- runif(1)
           print(paste("y is ", y))
         }
      }
```

### Control de ejecución (2)

- <font color="green">`ifelse()`</font> es una versión vectorizada
  <br>(Thomas Unternährer, R-help, 2003-04-17)
```{r}
odd.even <- function(x){
              ifelse(x %% 2 == 1, "Odd", "Even")
            }
mtf <- matrix(c(TRUE, FALSE, TRUE, TRUE), nrow = 2)
ifelse(mtf, 0, 1)
```
- <font color="green">`for(`</font>*variable.loop* <font color="green">`in`</font> *valores*<font color="green">`)`</font> *instrucción*
```{r}
for(i in 1:10) cat("el valor de i es", i, "\n")
continue.loop <- TRUE
x <- 0
while(continue.loop){
        x <- x + 1
        print(x)
        if( x > 10) continue.loop <- FALSE
      }
```
-  <font color="green">`break`</font> para salir de un loop.

### Cuando algo va mal

- [Debugging from Advanced R](https://adv-r.hadley.nz/debugging.html) de Hadley Wickham.

- [Debugging with the RStudio IDE](https://support.rstudio.com/hc/en-us/articles/205612627-Debugging-with-the-RStudio-IDE)

- Cuando se produce un error, <font color="green">`traceback()`</font>
    nos informa de la secuencia de llamadas antes del *crash*
    de nuestra función.
    Es útil cuando se producen mensajes de error incomprensibles.
- Cuando se producen errores o la función da resultados
    incorrectos o *warnings* indebidos podemos seguir la ejecución de la función.
- <font color="green">`browser`</font> interrumpe la ejecución a partir de
    ese punto y permite seguir la ejecución o examinar el entorno;
    con "n" paso a paso, si otra tecla sigue la ejecución normal.
    "Q" para salir.
- <font color="green">`debug`</font> es como poner un <font color="green">`browser`</font> al
    principio de la función y se ejecuta la función paso a paso.
    Se sale con "Q".
```{r eval=FALSE}
debug(my.buggy.function)
...
undebug(my.buggy.function)
```

### Ejemplo

```{r eval=FALSE}
my.f2 <- function(x, y){
          z <- rnorm(10) + y2 <- z * y + y3 <- z * y * x + return(y3 + 25)
          }
my.f2(runif(3), 1:4)
debug(my.f2)
my.f2(runif(3), 1:4)
undebug(my.f2)
# insertar un browser() y correr de nuevo
```

### Ejecución no interactiva

- Con <font color="green">`source()`</font> abrimos una sesión de R y hacemos
```{r eval=FALSE}
source("mi.fichero.con.codigo.R")
```
- Con BATCH:
```{r eval=FALSE}
$ Rcmd BATCH mi.fichero.con.codigo.R
```
- <font color="green">`source()`</font> es en ocasiones más útil porque informa
inmediatamente de errores en el código. BATCH no informa, pero no
requiere tener abierta una sesión (se puede correr en el
background).

- Ver la ayuda: <font color="green">`Rcmd BATCH --help`</font>
- Puede que necesitemos explícitos <font color="green">`print`</font> statements o
hacer <font color="green">`source(my.file.R, echo = TRUE)`</font>.
- <font color="green">`sink()`</font> es el inverso de <font color="green">`source()`</font> (lo manda todo a
un fichero).

\item Se pueden crear paquetes, con nuestras funciones, que se
comporten igual que los demás paquetes. Ver *Writing R extensions*.

\item R puede llamar código compilado en C/C++ y FORTRAN. Ver
<font color="green">`.C`</font>, <font color="green">`.Call`</font>, <font color="green">`.Fortran`</font>.

- *Lexical scoping* importante en programación más avanzada.

\item No hemos mencionado el *computing on the language* (ej.,
<font color="green">`do.call`</font>, <font color="green">`eval`</font>, etc.).

- R es un verdadero *object-oriented language*. Dos
implementaciones, las S3 classes y las S4 classes.

