Functions that eat functions

Master R

By Guangming Lang Comment

We human eat different kind of foods. Similarly, functions can eat different kind of things. We’ve seen functions that eat a number, a data frame, and a vector of numbers. Today, I’m going to show you how to create functions that eat functions. By that, I mean functions that take functions as input. For example, look at the following function.

arg_func = function(func) {
        function(x, f) {
                # x: a numeric vector
                # f: a function
                fvals = vapply(x, f, numeric(1))
                x[fvals == func(fvals)] # notice how func is used
        }
}

It uses a function as input (func) and outputs another function (function(x, f)). Notice the output function has two parameters: one is a numeric vector and the other is yet another function!

We can use arg_func to implement a function that takes a vector of numbers and a function as inputs, and returns the elements of the vector where the input function returns the biggest value.

arg_max = arg_func(max)

For example, when applying the function to the vector -10:5, it should obtain the biggest value at x=-10. And when appling it to -5:5, the maximum value should happen at x=-5 and x=5. Let’s see if arg_max() gives us the same results.

arg_max(-10:5, function(x) x ^ 2)
## [1] -10
arg_max(-5:5, function(x) x ^ 2)
## [1] -5  5

Indeed, arg_max() gives us the correct results. We can also implement arg_min() in the same fashion.

arg_min = arg_func(min)
arg_min(-10:5, function(x) x ^ 2)
## [1] 0
arg_min(-5:5, function(x) x ^ 2)
## [1] 0

Similarly, we can implement arg_mean() and arg_median().

# arg_mean()
arg_mean = arg_func(mean)
arg_mean(-10:5, function(x) x ^ 2)
## integer(0)
arg_mean(-5:5, function(x) x ^ 2)
## integer(0)
# arg_median()
arg_median = arg_func(median)
arg_median(-10:5, function(x) x ^ 2)
## [1] -4  4
arg_median(-5:5, function(x) x ^ 2)
## [1] -3  3

This article is inspired by Hadley’s book “Advanced R”, you can buy it from Amazon or read it online for FREE.

If you enjoyed this post, get updates. It's FREE