A common thing to do in functional programming is to create, within a (outer) function, a local (inner) function that uses other variables in scope. Let me give you an example. The function countup_from1()
uses a local helper function count()
to accumulate results recursively. Its argument x
is used directly inside count()
.
countup_from1 = function(x) { # x: integer
count = function(from) { # from: integer
if (from == x) x # can use x because count() is local
else c(from, count(from+1))
}
count(1)
}
countup_from1(10)
## [1] 1 2 3 4 5 6 7 8 9 10
Another common thing to do is to make local variables to store the results of expensive computations. Before I give you an example, let’s first define some helper functions.
# Check if a vector is empty. Returns TRUE if it is, FALSE otherwise.
is_empty = function(xs) { # xs: a vector of any type
length(xs) == 0
}
# Get the first element of a vector, raising an exception if the vector is empty.
hd = function(xs) { # xs: a vector of any type
if (is_empty(xs)) stop("Vector is empty.")
else xs[1]
}
# Get the tail of a vector without its first element, raising an exception if the vector is empty.
tl = function(xs) { # xs: a vector of any type
if (is_empty(xs)) stop("Vector is empty.")
else xs[-1]
}
Using these helpers, we can write a function that returns the max value of an integer vector. Without using local variables to store intermediate results, bad_max()
gets very expensive even for small-lengthed input vectors.
bad_max = function(xs) { # xs: integer vector
if (is_empty(xs)) 0
else if (is_empty(tl(xs))) hd(xs)
else if (hd(xs) > bad_max(tl(xs))) hd(xs) # recursive call to bad_max()
else bad_max(tl(xs)) # recursive call to bad_max(), these two recursive
# calls hugely slow down the computation.
}
bad_max(1:10)
## [1] 10
bad_max(1:20)
## [1] 20
# bad_max(1:30) # this will take "forever"!
We can re-write the function by using a local variable to store the intermediate result of the expensive recursive step.
good_max = function(xs) {
if (is_empty(xs)) 0
else if (is_empty(tl(xs))) hd(xs)
else {
tl_ans = good_max(tl(xs)) # use local variable to store expensive computation
hd_xs = hd(xs)
if (hd_xs > tl_ans) hd_xs
else tl_ans
}
}
good_max(1:30)
## [1] 30
good_max(1:100)
## [1] 100