使用 R,如何将所有参数及其值传递给函数?
Using R, How to get all parameters passed into a function, with their values?
我有一个功能
adebo.deepSearch = function(z, pi_0 = 0.3, families=list(), ... )
{
}
我想捕获通过名为 grabFunctionParameters
的函数传入的所有参数名称和值;例如,
adebo.deepSearch = function(z, pi_0 = 0.3, families=list(), ... )
{
args = grabFunctionParameters();
}
其中 args 是包含“键”和“值”的列表,例如
args[["pi_0"] = 0.3;
对于所有键和值,包括省略号 (...) 中的键和值。
理想的(可变的)解决方案是外部函数 grabFunctionParameters()
解决方案:
这是提供的已接受答案:
#
# nice work :: B. Christian Kamgang
# .GlobalEnv$.function.args.memory ... key memory on last function call ... so I could reference outside the function
grabFunctionParameters <- function() {
pf <- parent.frame()
args_names <- ls(envir = pf, all.names = TRUE, sorted = FALSE)
if("..." %in% args_names) {
dots <- eval(quote(list(...)), envir = pf)
} else {
dots = list()
}
args_names <- sapply(setdiff(args_names, "..."), as.name)
if(length(args_names)) {
not_dots <- lapply(args_names, eval, envir = pf)
} else {
not_dots <- list()
}
idx <- names(dots) != "";
list(.keys. = names(not_dots), .vals. = unname(not_dots), .fn. = as.character(sys.call(1L)[[1L]]), .scope. = pf, .dot.keys. = names(dots[idx]), .dot.vals. = unname(dots[idx]));
}
这是提供的已接受答案(格式略有不同):
grabFunctionParameters <- function()
{
pf = parent.frame();
my.names = ls(envir = pf, all.names = TRUE, sorted = FALSE);
dots = if("..." %in% my.names) { eval(quote(list(...)), envir = pf); } else { list(); }
dots.idx = ( names(dots) != "" );
remaining = sapply( setdiff(my.names, "..."), as.name);
not.dots = if(length(remaining) > 0) { lapply( remaining, eval, envir = pf); } else { list(); }
res = list();
res$.fn. = as.character( sys.call(1L)[[1L]] );
res$.scope. = pf;
res$.keys. = names( not.dots );
res$.vals. = not.dots; # unname(not_dots); # I want keys on "vals"
res$.dots.keys. = names( dots[dots.idx] );
res$.dots.vals. = dots[dots.idx]; # unname(dots[dots.idx]);
res;
}
adebo <- function(z, pi_0 = 0.3, families = list(), ...) {
args <- formals(adebo)
return(args)
}
adebo()
#> $z
#>
#>
#> $pi_0
#> [1] 0.3
#>
#> $families
#> list()
#>
#> $...
由 reprex package (v1.0.0)
于 2021-02-23 创建
您可以mget
函数环境。
adebo.deepSearch <- function(z, pi_0 = 0.3, families=list(), ... ) {
c(mget(ls(environment(), sorted=F)), match.call(expand.dots=F)$...)
}
adebo.deepSearch(foo=1, z=2)
# $z
# [1] 2
#
# $pi_0
# [1] 0.3
#
# $families
# list()
#
# $foo
# [1] 1
不是解决方案,而是捕获“...”部分的想法。 Returns 作为 quosure 或 quosures 列表传入的参数。
adebo <- function(z, pi_0 = 0.3, families = list(), ...) {
rlang::enquos(...)
}
adebo(trash = "trash", idea = "idea")
#> <list_of<quosure>>
#>
#> $trash
#> <quosure>
#> expr: ^"trash"
#> env: empty
#>
#> $idea
#> <quosure>
#> expr: ^"idea"
#> env: empty
由 reprex package (v1.0.0)
于 2021-02-23 创建
这是一种可能的解决方案。此解决方案需要指定没有默认值的函数参数(如下面的 z
)。
grabFunctionParameters <- function() {
pf <- parent.frame() # get caller environment
dots <- eval(quote(list(...)), envir = pf) # get ... in the caller
nms <- sapply(ls(envir = pf, sorted = FALSE), as.name) # get argument names different from names in ... in the caller
out <- c(lapply(nms, eval, envir = pf), dots) # get all arguments/values
out[names(out) != ""] # remove unnamed values in ... (if any)
}
用例示例
adebo.deepSearch = function(z, pi_0 = 0.3, families=list(), ... ) {
args = grabFunctionParameters();
args
}
部分场景
adebo.deepSearch(z=4)
# $z
# [1] 4
#
# $pi_0
# [1] 0.3
#
# $families
# list()
#
adebo.deepSearch(z=4, pi_0=9, families = list(z=1:2))
# $z
# [1] 4
#
# $pi_0
# [1] 9
#
# $families
# $families$z
# [1] 1 2
#
#
adebo.deepSearch(z=4, pi_0=9, ac=5, bc=6) # some additional arguments for ...
# $z
# [1] 4
#
# $pi_0
# [1] 9
#
# $families
# list()
#
# $ac
# [1] 5
#
# $bc
# [1] 6
Udapte:这是对上述功能的更新,使其更通用。
它总是return一个列表:
- 如果调用者(函数)没有参数(或只有...具有未命名的值),则为空列表。
- 正式参数名称(不在...中)可以以点开头。
前一个函数要求调用者有...;并且具有以点开头(不在...)的正式参数名称的调用者不是 return.
新功能
grabFunctionParameters <- function() {
pf <- parent.frame()
args_names <- ls(envir = pf, all.names = TRUE, sorted = FALSE)
if("..." %in% args_names) {
dots <- eval(quote(list(...)), envir = pf)
} else {
dots = list()
}
args_names <- sapply(setdiff(args_names, "..."), as.name)
if(length(args_names)) {
not_dots <- lapply(args_names, eval, envir = pf)
} else {
not_dots <- list()
}
out <- c(not_dots, dots)
out[names(out) != ""] # remove unnamed values in ... (if any)
}
部分场景
fn1 <- function() grabFunctionParameters() # the initial function (before the update) required ... argument
fn2 <- function(x=1, .a=2, b=list(), ...) grabFunctionParameters() # the initial function did not return .a
fn3 <- function(.x, .a=2, b=list(), ...) grabFunctionParameters()
fn4 <- function(...) grabFunctionParameters()
fn5 <- function(x, .a) grabFunctionParameters() # the initial function required ... argument
fn1() # correct since the caller has no argument. Previously not allowed!
# list()
fn2()
# $x
# [1] 1
#
# $.a
# [1] 2
#
# $b
# list()
fn2(.a=10, ac=4, bc=7, .xy=1) #
# $x
# [1] 1
#
# $.a
# [1] 10
#
# $b
# list()
#
# $ac
# [1] 4
#
# $bc
# [1] 7
#
# $.xy
# [1] 1
fn3(10)
# $.x
# [1] 10
#
# $.a
# [1] 2
#
# $b
# list()
fn3() # throw an error! (.x required!). This will not happen if we use mget function and not lapply/supply inside grabFunctionParameters above.
# Error in FUN(X[[i]], ...) : argument ".x" is missing, with no default
fn4(a = 5, b = 6, c = 6, 6, 7, 9) # unnamed values are dropped
# $a
# [1] 5
#
# $b
# [1] 6
#
# $c
# [1] 6
fn5(6, 8)
# $x
# [1] 6
#
# $.a
# [1] 8
我有一个功能
adebo.deepSearch = function(z, pi_0 = 0.3, families=list(), ... )
{
}
我想捕获通过名为 grabFunctionParameters
的函数传入的所有参数名称和值;例如,
adebo.deepSearch = function(z, pi_0 = 0.3, families=list(), ... )
{
args = grabFunctionParameters();
}
其中 args 是包含“键”和“值”的列表,例如
args[["pi_0"] = 0.3;
对于所有键和值,包括省略号 (...) 中的键和值。
理想的(可变的)解决方案是外部函数 grabFunctionParameters()
解决方案:
这是提供的已接受答案:#
# nice work :: B. Christian Kamgang
# .GlobalEnv$.function.args.memory ... key memory on last function call ... so I could reference outside the function
grabFunctionParameters <- function() {
pf <- parent.frame()
args_names <- ls(envir = pf, all.names = TRUE, sorted = FALSE)
if("..." %in% args_names) {
dots <- eval(quote(list(...)), envir = pf)
} else {
dots = list()
}
args_names <- sapply(setdiff(args_names, "..."), as.name)
if(length(args_names)) {
not_dots <- lapply(args_names, eval, envir = pf)
} else {
not_dots <- list()
}
idx <- names(dots) != "";
list(.keys. = names(not_dots), .vals. = unname(not_dots), .fn. = as.character(sys.call(1L)[[1L]]), .scope. = pf, .dot.keys. = names(dots[idx]), .dot.vals. = unname(dots[idx]));
}
这是提供的已接受答案(格式略有不同):
grabFunctionParameters <- function()
{
pf = parent.frame();
my.names = ls(envir = pf, all.names = TRUE, sorted = FALSE);
dots = if("..." %in% my.names) { eval(quote(list(...)), envir = pf); } else { list(); }
dots.idx = ( names(dots) != "" );
remaining = sapply( setdiff(my.names, "..."), as.name);
not.dots = if(length(remaining) > 0) { lapply( remaining, eval, envir = pf); } else { list(); }
res = list();
res$.fn. = as.character( sys.call(1L)[[1L]] );
res$.scope. = pf;
res$.keys. = names( not.dots );
res$.vals. = not.dots; # unname(not_dots); # I want keys on "vals"
res$.dots.keys. = names( dots[dots.idx] );
res$.dots.vals. = dots[dots.idx]; # unname(dots[dots.idx]);
res;
}
adebo <- function(z, pi_0 = 0.3, families = list(), ...) {
args <- formals(adebo)
return(args)
}
adebo()
#> $z
#>
#>
#> $pi_0
#> [1] 0.3
#>
#> $families
#> list()
#>
#> $...
由 reprex package (v1.0.0)
于 2021-02-23 创建您可以mget
函数环境。
adebo.deepSearch <- function(z, pi_0 = 0.3, families=list(), ... ) {
c(mget(ls(environment(), sorted=F)), match.call(expand.dots=F)$...)
}
adebo.deepSearch(foo=1, z=2)
# $z
# [1] 2
#
# $pi_0
# [1] 0.3
#
# $families
# list()
#
# $foo
# [1] 1
不是解决方案,而是捕获“...”部分的想法。 Returns 作为 quosure 或 quosures 列表传入的参数。
adebo <- function(z, pi_0 = 0.3, families = list(), ...) {
rlang::enquos(...)
}
adebo(trash = "trash", idea = "idea")
#> <list_of<quosure>>
#>
#> $trash
#> <quosure>
#> expr: ^"trash"
#> env: empty
#>
#> $idea
#> <quosure>
#> expr: ^"idea"
#> env: empty
由 reprex package (v1.0.0)
于 2021-02-23 创建这是一种可能的解决方案。此解决方案需要指定没有默认值的函数参数(如下面的 z
)。
grabFunctionParameters <- function() {
pf <- parent.frame() # get caller environment
dots <- eval(quote(list(...)), envir = pf) # get ... in the caller
nms <- sapply(ls(envir = pf, sorted = FALSE), as.name) # get argument names different from names in ... in the caller
out <- c(lapply(nms, eval, envir = pf), dots) # get all arguments/values
out[names(out) != ""] # remove unnamed values in ... (if any)
}
用例示例
adebo.deepSearch = function(z, pi_0 = 0.3, families=list(), ... ) {
args = grabFunctionParameters();
args
}
部分场景
adebo.deepSearch(z=4)
# $z
# [1] 4
#
# $pi_0
# [1] 0.3
#
# $families
# list()
#
adebo.deepSearch(z=4, pi_0=9, families = list(z=1:2))
# $z
# [1] 4
#
# $pi_0
# [1] 9
#
# $families
# $families$z
# [1] 1 2
#
#
adebo.deepSearch(z=4, pi_0=9, ac=5, bc=6) # some additional arguments for ...
# $z
# [1] 4
#
# $pi_0
# [1] 9
#
# $families
# list()
#
# $ac
# [1] 5
#
# $bc
# [1] 6
Udapte:这是对上述功能的更新,使其更通用。
它总是return一个列表:
- 如果调用者(函数)没有参数(或只有...具有未命名的值),则为空列表。
- 正式参数名称(不在...中)可以以点开头。 前一个函数要求调用者有...;并且具有以点开头(不在...)的正式参数名称的调用者不是 return.
新功能
grabFunctionParameters <- function() {
pf <- parent.frame()
args_names <- ls(envir = pf, all.names = TRUE, sorted = FALSE)
if("..." %in% args_names) {
dots <- eval(quote(list(...)), envir = pf)
} else {
dots = list()
}
args_names <- sapply(setdiff(args_names, "..."), as.name)
if(length(args_names)) {
not_dots <- lapply(args_names, eval, envir = pf)
} else {
not_dots <- list()
}
out <- c(not_dots, dots)
out[names(out) != ""] # remove unnamed values in ... (if any)
}
部分场景
fn1 <- function() grabFunctionParameters() # the initial function (before the update) required ... argument
fn2 <- function(x=1, .a=2, b=list(), ...) grabFunctionParameters() # the initial function did not return .a
fn3 <- function(.x, .a=2, b=list(), ...) grabFunctionParameters()
fn4 <- function(...) grabFunctionParameters()
fn5 <- function(x, .a) grabFunctionParameters() # the initial function required ... argument
fn1() # correct since the caller has no argument. Previously not allowed!
# list()
fn2()
# $x
# [1] 1
#
# $.a
# [1] 2
#
# $b
# list()
fn2(.a=10, ac=4, bc=7, .xy=1) #
# $x
# [1] 1
#
# $.a
# [1] 10
#
# $b
# list()
#
# $ac
# [1] 4
#
# $bc
# [1] 7
#
# $.xy
# [1] 1
fn3(10)
# $.x
# [1] 10
#
# $.a
# [1] 2
#
# $b
# list()
fn3() # throw an error! (.x required!). This will not happen if we use mget function and not lapply/supply inside grabFunctionParameters above.
# Error in FUN(X[[i]], ...) : argument ".x" is missing, with no default
fn4(a = 5, b = 6, c = 6, 6, 7, 9) # unnamed values are dropped
# $a
# [1] 5
#
# $b
# [1] 6
#
# $c
# [1] 6
fn5(6, 8)
# $x
# [1] 6
#
# $.a
# [1] 8