gpt4 book ai didi

r - 访问具有原始函数名称的函数参数

转载 作者:行者123 更新时间:2023-12-05 04:39:57 24 4
gpt4 key购买 nike

我正在尝试理解用户定义函数的行为,如下所示(基于对 this 问题的第一个答案),它返回作为命名列表提供给它的参数:

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”是显式参数之一并且缺失,函数返回错误

#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

我已经尝试了上面的许多变体,考虑到基本模式应该清晰并且无需特定代码段就可以轻松重现,这些变体在这里打印似乎毫无意义;可以这么说,据我所知,如果函数的其中一个参数 a.) 与原始函数同名,而原始函数的唯一参数是 ... 和 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

请有人解释为什么我看到这种行为模式,以及只有 ... 作为参数的原始函数显然扮演关键角色的原因。

请不要提交建议“解决方法”或质疑手头问题的实际意义的答案或评论。我问我的问题并不是为了解决一个具体的实际问题,我也没有理由想到为什么我会被迫使用原始函数的名称作为参数;相反,我想了解错误发生的原因,以便更清楚地了解一般情况下的功能,以及用于访问其参数的过程在 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 中找到它,否则它在函数环境中“找到”它(其中 ab 也被定义了):

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 创建于 2021-12-15 (v2.0.1)

关于r - 访问具有原始函数名称的函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70366747/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com