Ailton is right when he says
operator is a particular factory case.
But I’ll illustrate this idea better. There are factories of functions that can be of different types, I will show factories that are of the type operator and factories that are not.
Factories - the general case
The motivation of a function factory is to make a metafunction, ie a function that creates other functions. With it we are able to abstract the process of creating similar functions.
A great example of factories within the r are the functions color*
package leaflet. These functions return functions that map value in color.
verdes <- leaflet::colorNumeric("Greens", c(0, 4))
args(verdes)
# function (x)
# NULL
The factory allows us to create a color palette very similar to red, for example.
vermelhos <- leaflet::colorNumeric("Reds", c(0,4))
verdes(2)
# [1] "#74C476"
vermelhos(2)
# [1] "#FB6A4A"
Note, however, that the general definition of factory so far allows us to include in it any functions that return a function, without including restrictions or special cases. to colorNumeric
, for example, use text and numbers to create its function.
Functional operator - the specific case
It is possible to think of a specific factory case. A type that receives functions to build the returned function. This idea allows us to create abstractions to think about how to modify the received functions as arguments.
A functional operator does not necessarily need to operate only functions, it can receive arguments of other types as well. It is necessary, however, to receive at least one function within your arguments.
In the chapter of Hadley Wickham quoted he lists four types of operators:
- Behavioral
- Output ()
- Input ()
- Combination
An example would be to create one’s own pipe
.
pipe <- function(...) {
dots <- list(...)
function(x) {
for (i in seq_along(dots)) {
x <- dots[[i]](x)
}
x
}
}
soma_raizes <- pipe(sqrt, sum)
soma_raizes(c(1, 4, 9))
# [1] 6
Good examples of functional operators in the tidyverse sane purrr::safely()
and purrr::quietly()
.