The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
section_fun()The section_fun utility in doBy creates a new function by fixing some arguments of an existing function. The result is a section of the original function, defined only on the remaining arguments.
For example, if you have:
$$ f(x,y) = x + y $$
then fixing \(x=10\) yields:
$$ f_x(y) = 10 + y $$
In R terms, section_fun lets you programmatically create such specialized versions.
section_fun workssection_fun() offers three ways to fix arguments:
Example:
fun <- function(a, b, c=4, d=9) {
a + b + c + d
}
fun_def <- section_fun(fun, list(b=7, d=10))
fun_def
#> function (a, c = 4, b = 7, d = 10)
#> {
#> a + b + c + d
#> }
fun_body <- section_fun(fun, list(b=7, d=10), method="sub")
fun_body
#> function (a, c = 4)
#> {
#> b = 7
#> d = 10
#> a + b + c + d
#> }
fun_env <- section_fun(fun, list(b=7, d=10), method = "env")
fun_env
#> function (a, c = 4)
#> {
#> . <- "use get_section(function_name) to see section"
#> . <- "use get_fun(function_name) to see original function"
#> args <- arg_getter()
#> do.call(fun, args)
#> }
#> <environment: 0x5d58c7af6838>
You can inspect the environment-based section:
get_section(fun_env)
#> $b
#> [1] 7
#>
#> $d
#> [1] 10
## same as: attr(fun_env, "arg_env")$args
get_fun(fun_env)
#> <srcref: file "" chars 1:9 to 3:1>
## same as: environment(fun_env)$fun
Example evaluations:
fun(a=10, b=7, c=5, d=10)
#> [1] 32
fun_def(a=10, c=5)
#> [1] 32
fun_body(a=10, c=5)
#> [1] 32
fun_env(a=10, c=5)
#> [1] 32
Suppose you want to benchmark a function for different input values without writing repetitive code:
inv_toep <- function(n) {
solve(toeplitz(1:n))
}
Instead of typing the following
microbenchmark(
inv_toep(4), inv_toep(8), inv_toep(16),
times=3
)
you can create specialized versions programmatically:
n.vec <- c(4, 8, 16)
fun_list <- lapply(n.vec,
function(ni) {
section_fun(inv_toep, list(n=ni))
})
fun_list
#> [[1]]
#> function (n = 4)
#> {
#> solve(toeplitz(1:n))
#> }
#>
#> [[2]]
#> function (n = 8)
#> {
#> solve(toeplitz(1:n))
#> }
#>
#> [[3]]
#> function (n = 16)
#> {
#> solve(toeplitz(1:n))
#> }
Inspect and evaluate:
fun_list[[1]]
#> function (n = 4)
#> {
#> solve(toeplitz(1:n))
#> }
fun_list[[1]]()
#> [,1] [,2] [,3] [,4]
#> [1,] -0.4 0.5 0.0 0.1
#> [2,] 0.5 -1.0 0.5 0.0
#> [3,] 0.0 0.5 -1.0 0.5
#> [4,] 0.1 0.0 0.5 -0.4
To use with microbenchmark, we need expressions:
bquote_list <- function(fun_list) {
lapply(fun_list, function(g){
bquote(.(g)())
})
}
We get:
bq_fun_list <- bquote_list(fun_list)
bq_fun_list
#> [[1]]
#> (function (n = 4)
#> {
#> solve(toeplitz(1:n))
#> })()
#>
#> [[2]]
#> (function (n = 8)
#> {
#> solve(toeplitz(1:n))
#> })()
#>
#> [[3]]
#> (function (n = 16)
#> {
#> solve(toeplitz(1:n))
#> })()
bq_fun_list[[1]]
#> (function (n = 4)
#> {
#> solve(toeplitz(1:n))
#> })()
eval(bq_fun_list[[1]])
#> [,1] [,2] [,3] [,4]
#> [1,] -0.4 0.5 0.0 0.1
#> [2,] 0.5 -1.0 0.5 0.0
#> [3,] 0.0 0.5 -1.0 0.5
#> [4,] 0.1 0.0 0.5 -0.4
Now run:
microbenchmark(
list = bq_fun_list,
times = 5
)
#> Unit: microseconds
#> expr min lq mean median
#> (function (n = 4) { solve(toeplitz(1:n)) })() 8.93 9.04 23.3 10.1
#> (function (n = 8) { solve(toeplitz(1:n)) })() 10.04 10.60 12.0 12.4
#> (function (n = 16) { solve(toeplitz(1:n)) })() 15.96 16.35 18.7 17.1
#> uq max neval cld
#> 12.9 75.4 5 a
#> 13.2 13.7 5 a
#> 19.1 25.1 5 a
Running the code below provides a benchmark of the different ways of sectioning in terms of speed.
n.vec <- seq(20, 80, by=20)
fun_def <- lapply(n.vec,
function(n){
section_fun(inv_toep, list(n=n), method="def")
})
fun_body <- lapply(n.vec,
function(n){
section_fun(inv_toep, list(n=n), method="sub")
})
fun_env <- lapply(n.vec,
function(n){
section_fun(inv_toep, list(n=n), method="env")
})
names(fun_def) <- paste0("def", n.vec)
names(fun_body) <- paste0("body", n.vec)
names(fun_env) <- paste0("env", n.vec)
bq_fun_list <- bquote_list(c(fun_def, fun_body, fun_env))
bq_fun_list |> head()
#> $def20
#> (function (n = 20)
#> {
#> solve(toeplitz(1:n))
#> })()
#>
#> $def40
#> (function (n = 40)
#> {
#> solve(toeplitz(1:n))
#> })()
#>
#> $def60
#> (function (n = 60)
#> {
#> solve(toeplitz(1:n))
#> })()
#>
#> $def80
#> (function (n = 80)
#> {
#> solve(toeplitz(1:n))
#> })()
#>
#> $body20
#> (function ()
#> {
#> n = 20
#> solve(toeplitz(1:n))
#> })()
#>
#> $body40
#> (function ()
#> {
#> n = 40
#> solve(toeplitz(1:n))
#> })()
mb <- microbenchmark(
list = bq_fun_list,
times = 2
)
mb
#> Unit: microseconds
#> expr min lq mean median uq max neval cld
#> def20 29.3 29.3 38.7 38.7 48.1 48.1 2 a
#> def40 76.4 76.4 80.7 80.7 85.1 85.1 2 a
#> def60 168.9 168.9 181.9 181.9 195.0 195.0 2 a
#> def80 343.8 343.8 344.6 344.6 345.5 345.5 2 a
#> body20 42.9 42.9 427.8 427.8 812.6 812.6 2 a
#> body40 104.6 104.6 535.5 535.5 966.4 966.4 2 a
#> body60 267.4 267.4 691.1 691.1 1114.9 1114.9 2 a
#> body80 518.9 518.9 961.4 961.4 1404.0 1404.0 2 a
#> env20 28.3 28.3 41.0 41.0 53.6 53.6 2 a
#> env40 84.4 84.4 620.9 620.9 1157.5 1157.5 2 a
#> env60 184.5 184.5 232.9 232.9 281.4 281.4 2 a
#> env80 345.0 345.0 353.5 353.5 362.1 362.1 2 a
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.