访问具有原始函数名称的函数参数
Access function arguments with names of primitive functions
我正在尝试理解如下用户定义函数的行为(基于对 this 问题的第一个答案),returns 作为命名列表提供给它的参数:
function(a, b, ...) {
argg <- c(as.list(environment()), list(...))
print(argg)
}
本质上,当其中一个参数名称也是原始函数的名称时,像上面这样的函数会产生意想不到的行为,该函数的唯一参数是 ...
下面是一些可重现的例子。
示例 1 - 函数按预期运行,缺少参数不会导致错误
#define function as above
fun1 <- function(a, b, ...) {
argg <- c(as.list(environment()), list(...))
print(argg)
}
#run function
fun1(a = 1)
#returns the below. note that $b has the missing argument and this does not cause an error
#$a
#[1] 1
#$b
示例 2 - 如果 'c' 是显式参数之一并且缺少
,则函数 returns 出错
#define function as above but with new explicit argument, called 'c'
#note that c() is a primitive function whose only parameter is ...
fun2 <- function(a, b, c, ...) {
argg <- c(as.list(environment()), list(...))
print(argg)
}
#run function
fun2(a = 1)
#returns error:
#Error in c(as.list(environment()), list(...)) :
# argument "c" is missing, with no default
示例 3 - 将 'c' 替换为 'switch',一个参数不是 ...
的原始函数
#define function same way as fun2, but change 'c' parameter to 'switch'
#note that switch() is a primitive function that has parameters other than ...
fun3 <- function(a, b, switch, ...) {
argg <- c(as.list(environment()), list(...))
print(argg)
}
#run function
fun3(a = 1)
#returns the below. note that $b and $switch have the missing argument and this does not cause an error
#$a
#[1] 1
#$b
#$switch
我已经尝试了上面的许多变体,考虑到基本模式应该是清晰的,因此在没有特定代码段落的情况下很容易重现,但在这里打印似乎毫无意义;可以说,据我所知,函数 returns 如果其中一个参数 a.) 与原始函数同名,其唯一参数是 [=15= ,则似乎是一个错误] 和 b.) 也不见了。我没有测试其他更改(例如从用户定义函数的参数中删除 ...
;更改调用函数或定义函数时指定参数的顺序;更改其他参数的名称和数量调用函数或定义函数等时指定的参数)对行为是否符合预期有影响。
另一点需要注意的是,如果我定义一个与 fun2 具有相同参数的函数,并且仍然缺少 c
参数,如果我不尝试访问函数的参数在里面。例如:
#define function with same parameters but different content to fun2
fun4 <- function(a, b, c, ...) {
return(a+b)
}
#run function
fun4(a = 1, b = 2)
#returns
#[1] 3
请有人解释为什么我看到这种行为模式,以及只有 ...
作为参数的原始函数显然发挥关键作用的原因。
请不要提交建议 'workarounds' 或质疑手头问题的实际意义的答案或评论。我问我的问题并不是为了解决一个具体的实际问题,我也没有理由想到为什么我会被迫使用原始函数的名称作为参数;相反,我想了解错误发生的原因,以便更清楚地了解一般情况下的功能,以及用于访问其参数的过程在 R 中的工作方式。
不是 ...
引起的问题。当您调用 c()
时,R 在环境中查找函数定义。在函数之外,它通常会发现它是 base::c
。但是在您的函数中,它首先在函数调用的参数 c
中查找定义,然后找不到。这种调用方式表明它可以通过告诉 R 具体在哪里找到 c
:
的定义来工作
fun4 <- function(a, b, c, ...) {
argg <- base::c(as.list(environment()), list(...))
print(argg)
}
#run function
fun4(a = 1)
#> $a
#> [1] 1
#>
#> $b
#>
#>
#> $c
环境 - 来自 Advanced R
要演示调用对象的位置,您可以使用 Advanced R by Hadley Wickham 中的技巧来查看 R 在哪里找到每个对象。在 c
不是参数的函数中,它在 base
中找到它,否则它在函数环境中“找到”它(其中 a
和 b
也是定义):
library(rlang)
where <- function(name, env = caller_env()) {
if (identical(env, empty_env())) {
stop("Can't find ", name, call. = FALSE)
} else if (env_has(env, name)) {
env
} else {
where(name, env_parent(env))
}
}
fun5 <- function(a, b, ...) {
print(where("a"))
print(where("b"))
print(where("c"))
}
#run function
fun5(a = 1)
#> <environment: 0x000000001de35890>
#> <environment: 0x000000001de35890>
#> <environment: base>
fun6 <- function(a, b, c, ...) {
print(where("a"))
print(where("b"))
print(where("c"))
}
#run function
fun6(a = 1)
#> <environment: 0x000000001e1381f0>
#> <environment: 0x000000001e1381f0>
#> <environment: 0x000000001e1381f0>
由 reprex package (v2.0.1)
于 2021-12-15 创建
我正在尝试理解如下用户定义函数的行为(基于对 this 问题的第一个答案),returns 作为命名列表提供给它的参数:
function(a, b, ...) {
argg <- c(as.list(environment()), list(...))
print(argg)
}
本质上,当其中一个参数名称也是原始函数的名称时,像上面这样的函数会产生意想不到的行为,该函数的唯一参数是 ...
下面是一些可重现的例子。
示例 1 - 函数按预期运行,缺少参数不会导致错误
#define function as above
fun1 <- function(a, b, ...) {
argg <- c(as.list(environment()), list(...))
print(argg)
}
#run function
fun1(a = 1)
#returns the below. note that $b has the missing argument and this does not cause an error
#$a
#[1] 1
#$b
示例 2 - 如果 'c' 是显式参数之一并且缺少
,则函数 returns 出错#define function as above but with new explicit argument, called 'c'
#note that c() is a primitive function whose only parameter is ...
fun2 <- function(a, b, c, ...) {
argg <- c(as.list(environment()), list(...))
print(argg)
}
#run function
fun2(a = 1)
#returns error:
#Error in c(as.list(environment()), list(...)) :
# argument "c" is missing, with no default
示例 3 - 将 'c' 替换为 'switch',一个参数不是 ...
的原始函数
#define function same way as fun2, but change 'c' parameter to 'switch'
#note that switch() is a primitive function that has parameters other than ...
fun3 <- function(a, b, switch, ...) {
argg <- c(as.list(environment()), list(...))
print(argg)
}
#run function
fun3(a = 1)
#returns the below. note that $b and $switch have the missing argument and this does not cause an error
#$a
#[1] 1
#$b
#$switch
我已经尝试了上面的许多变体,考虑到基本模式应该是清晰的,因此在没有特定代码段落的情况下很容易重现,但在这里打印似乎毫无意义;可以说,据我所知,函数 returns 如果其中一个参数 a.) 与原始函数同名,其唯一参数是 [=15= ,则似乎是一个错误] 和 b.) 也不见了。我没有测试其他更改(例如从用户定义函数的参数中删除 ...
;更改调用函数或定义函数时指定参数的顺序;更改其他参数的名称和数量调用函数或定义函数等时指定的参数)对行为是否符合预期有影响。
另一点需要注意的是,如果我定义一个与 fun2 具有相同参数的函数,并且仍然缺少 c
参数,如果我不尝试访问函数的参数在里面。例如:
#define function with same parameters but different content to fun2
fun4 <- function(a, b, c, ...) {
return(a+b)
}
#run function
fun4(a = 1, b = 2)
#returns
#[1] 3
请有人解释为什么我看到这种行为模式,以及只有 ...
作为参数的原始函数显然发挥关键作用的原因。
请不要提交建议 'workarounds' 或质疑手头问题的实际意义的答案或评论。我问我的问题并不是为了解决一个具体的实际问题,我也没有理由想到为什么我会被迫使用原始函数的名称作为参数;相反,我想了解错误发生的原因,以便更清楚地了解一般情况下的功能,以及用于访问其参数的过程在 R 中的工作方式。
不是 ...
引起的问题。当您调用 c()
时,R 在环境中查找函数定义。在函数之外,它通常会发现它是 base::c
。但是在您的函数中,它首先在函数调用的参数 c
中查找定义,然后找不到。这种调用方式表明它可以通过告诉 R 具体在哪里找到 c
:
fun4 <- function(a, b, c, ...) {
argg <- base::c(as.list(environment()), list(...))
print(argg)
}
#run function
fun4(a = 1)
#> $a
#> [1] 1
#>
#> $b
#>
#>
#> $c
环境 - 来自 Advanced R
要演示调用对象的位置,您可以使用 Advanced R by Hadley Wickham 中的技巧来查看 R 在哪里找到每个对象。在 c
不是参数的函数中,它在 base
中找到它,否则它在函数环境中“找到”它(其中 a
和 b
也是定义):
library(rlang)
where <- function(name, env = caller_env()) {
if (identical(env, empty_env())) {
stop("Can't find ", name, call. = FALSE)
} else if (env_has(env, name)) {
env
} else {
where(name, env_parent(env))
}
}
fun5 <- function(a, b, ...) {
print(where("a"))
print(where("b"))
print(where("c"))
}
#run function
fun5(a = 1)
#> <environment: 0x000000001de35890>
#> <environment: 0x000000001de35890>
#> <environment: base>
fun6 <- function(a, b, c, ...) {
print(where("a"))
print(where("b"))
print(where("c"))
}
#run function
fun6(a = 1)
#> <environment: 0x000000001e1381f0>
#> <environment: 0x000000001e1381f0>
#> <environment: 0x000000001e1381f0>
由 reprex package (v2.0.1)
于 2021-12-15 创建