## Programming in R¶

### Defining Functions¶

In R, functions are "first class" objects.

In :
g = function(x) {
sin(x) * exp(-0.01*x)  # not: y = ...
}                          # but: return(y)

g
g(1)

Out:
function (x)
{
sin(x) * exp(-0.01 * x)
}
Out:
0.833098208613807

The last evaluated expression is returned.
NOTE: Assignments do not return a value!

R supports "local scoping" rules:

In :
a = 0.05
g = function(x) sin(x) * exp(-a*x)
g(1)

a = 0.10
g(1)

Out:
0.800431960612864
Out:
0.761394433245753

Keywords with default values are allowed.

In :
g = function(x, a=0.1)
return(sin(x) * exp(-a*x))


As objects, functions can be defined within functions. And they can be used as variables for other functions.

In :
curve(g, 0, 6*pi, col=4)
grid()


NOTE: Some functions, such as curve() or integrate() require the function to be vectorized.

In :
integrate(g, 0, 2*pi, a=0.1)

Out:
0.461893 with absolute error < 3.3e-14

Variables are passed as values, not as pointers, thus they cannot be changed with the function.
As a consequence: more memory will be needed, especially when a variable is a big dataframe.
[copy-by-demand/change + laziness]

When several return values shall be returned, a list will be needed -- multiple assignments are not possible.

In :
min_ind <- function(x) {
m <- min(x)
i <- (1:length(x))[x == m]
list(min=m, inds=i)
}

x = c(4,5,6,3,7,8,3,3,9)
res = min_ind(x)
cat("The minimum is", res$min, "and the indices are:", res$inds, "\n")

The minimum is 3 and the indices are: 4 7 8


### Flow Control¶

for (i in 1:n) {            while (...) {               if (...) {
...                         ...                         ...
}                           }                           } else {
...
for (a in vec) {            repeat {                    }
...                         ...
}                               break
}
In :
mySqrt = function(a, n=2) {
x0 = Inf
x1 = 1
while (abs(x1-x0) > 1e-15) {
x0 = x1
x1 = x0 - (x0^n - a) / n / x0^(n-1)
}
x1
}

mySqrt(2, 5)
2^0.2

Out:
1.14869835499704
Out:
1.14869835499704

### apply Functions¶

In :
A = matrix(1:12, 4, 3)
A
apply(A, 1, mean)
apply(A, 2, mean)

Out:
 1 5 9 2 6 10 3 7 11 4 8 12
Out:
1. 5
2. 6
3. 7
4. 8
Out:
1. 2.5
2. 6.5
3. 10.5
In :
X = list(x=1, y=c('a','b','c'), z=rep(0,100))
lapply(X, length)
sapply(X, length)

Out:
$x 1$y
3
$z 100 Out: x 1 y 3 z 100 ### S3 Methods¶ In : minind <- function(x) { m <- min(x) i <- (1:length(x))[x == m] r = list(min=m, inds=i) class(r) <- "minind" r } print.minind <- function(r) { cat("The minimum is", res$min, "and the indices are:", res$inds, "\n") }  In : x <- c(4,5,6,3,7,8,3,3,9) res = minind(x) res str(res)  Out: The minimum is 3 and the indices are: 4 7 8  List of 2$ min : num 3
\$ inds: int [1:3] 4 7 8
- attr(*, "class")= chr "minind"


### Debugging¶

For debugging purposes, it is best to use the features RStudio is providing.

Also:

options(error=recover)     # options(error=NULL)
trace(fun)                 # untrace(fun)
debug(fun)                 # undebug(fun), also: debugonce(fun)
setBreakpoint(file, line)  # clear=TRUE



These functions will call the browser: browse