获取作为参数传递给函数的函数的名称
Getting name of a function passed as an argument to a function
背景
函数作为参数传递给函数。问题涉及:
- 获取该函数的名称作为字符串以方便后续操作
- 在调用的包中定位该函数
- 理解
::
和:::
调用
例子
函数 fun_tst
在 x:
上执行函数 FUN
fun_tst <- function(x = 1:100, FUN = mean) {
return(FUN(x))
}
mean
fun_tst()
# [1] 50.5
sum
fun_tst(x = 1:1e3, FUN = sum)
# [1] 500500
问题
fun_tst <- function(x = 1:100, FUN = mean) {
msg <- paste("Executing function", FUN)
print(msg)
return(FUN(x))
}
fun_tst(x = 1:1e3, FUN = sum)
Error in paste("Executing function", FUN) : cannot coerce type
'builtin' to vector of type 'character'
尝试次数
1)
有趣的是,print
可以处理 FUN
对象,但结果是 return 函数体。
fun_tst <- function(x = 1:100, FUN = mean) {
print(FUN)
return(FUN(x))
}
fun_tst(x = 1:1e3, FUN = sum)
function (..., na.rm = FALSE) .Primitive("sum") [1] 500500
2) subsitute
fun_tst <- function(x = 1:100, FUN = mean) {
fun_name <- substitute(FUN)
msg <- paste("Executing function", fun_name, collapse = " ")
print(msg)
return(FUN(x))
}
fun_tst(x = 1:1e3, FUN = sum)
>> fun_tst(x = 1:1e3, FUN = sum)
[1] "Executing function sum"
[1] 500500
差不多了,但是当与 ::
一起使用时看起来一团糟,如:
>> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
[1] "Executing function :: Executing function dplyr Executing function glimpse"
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ..
想要的结果
fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
# Executing function glimpse from package dplyr
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
fun_tst(x = 1:1e3, FUN = sum)
# Executing function sum from package base
您第二次尝试(使用 substitute
)就快完成了。问题来自 R 将 language
对象转换为字符的方式:
> as.character(substitute(dplyr::glimpse))
[1] "::" "dplyr" "glimpse"
鉴于此,paste
以这种方式破坏它也就不足为奇了。我会通过分别处理这两种情况来解决这个问题:
fun_tst <- function(x = 1:100, FUN = mean) {
fun_name <- substitute(FUN)
if (length(fun_name) == 1) {
msg <- paste("Executing function", fun_name, "from package base")
} else {
msg <- paste("Executing function", fun_name[3], "from package", fun_name[2])
}
print(msg)
return(FUN(x))
}
这适用于您的两个示例:
> fun_tst(x = 1:1e3, FUN = sum)
[1] "Executing function sum from package base"
[1] 500500
> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
[1] "Executing function glimpse from package dplyr"
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
然而,如所写,它会认为全局环境中的所有函数都来自 base
,即使它们是用户定义的或通过 library
调用引入的。如果这是您的用例,请不要明确说明 "from package base".
如果您使用 deparse()
和 substitute
,您将获得所需的输出,请参阅将变量名称传递给 plot()
、[=16= 时类似的 post ].
fun_tst <- function(x = 1:100, FUN = mean) {
message(paste("Executing function",deparse(substitute(FUN))))
return((FUN(x)))
}
> fun_tst(x = 1:1e3, FUN = sum)
Executing function sum
[1] 500500
> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
Executing function dplyr::glimpse
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
如果您希望将消息作为字符向量,请将 message
替换为 print
。
背景
函数作为参数传递给函数。问题涉及:
- 获取该函数的名称作为字符串以方便后续操作
- 在调用的包中定位该函数
- 理解
::
和:::
调用
例子
函数 fun_tst
在 x:
FUN
fun_tst <- function(x = 1:100, FUN = mean) {
return(FUN(x))
}
mean
fun_tst()
# [1] 50.5
sum
fun_tst(x = 1:1e3, FUN = sum)
# [1] 500500
问题
fun_tst <- function(x = 1:100, FUN = mean) {
msg <- paste("Executing function", FUN)
print(msg)
return(FUN(x))
}
fun_tst(x = 1:1e3, FUN = sum)
Error in paste("Executing function", FUN) : cannot coerce type 'builtin' to vector of type 'character'
尝试次数
1)
有趣的是,print
可以处理 FUN
对象,但结果是 return 函数体。
fun_tst <- function(x = 1:100, FUN = mean) {
print(FUN)
return(FUN(x))
}
fun_tst(x = 1:1e3, FUN = sum)
function (..., na.rm = FALSE) .Primitive("sum") [1] 500500
2) subsitute
fun_tst <- function(x = 1:100, FUN = mean) {
fun_name <- substitute(FUN)
msg <- paste("Executing function", fun_name, collapse = " ")
print(msg)
return(FUN(x))
}
fun_tst(x = 1:1e3, FUN = sum)
>> fun_tst(x = 1:1e3, FUN = sum)
[1] "Executing function sum"
[1] 500500
差不多了,但是当与 ::
一起使用时看起来一团糟,如:
>> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
[1] "Executing function :: Executing function dplyr Executing function glimpse"
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ..
想要的结果
fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
# Executing function glimpse from package dplyr
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
fun_tst(x = 1:1e3, FUN = sum)
# Executing function sum from package base
您第二次尝试(使用 substitute
)就快完成了。问题来自 R 将 language
对象转换为字符的方式:
> as.character(substitute(dplyr::glimpse))
[1] "::" "dplyr" "glimpse"
鉴于此,paste
以这种方式破坏它也就不足为奇了。我会通过分别处理这两种情况来解决这个问题:
fun_tst <- function(x = 1:100, FUN = mean) {
fun_name <- substitute(FUN)
if (length(fun_name) == 1) {
msg <- paste("Executing function", fun_name, "from package base")
} else {
msg <- paste("Executing function", fun_name[3], "from package", fun_name[2])
}
print(msg)
return(FUN(x))
}
这适用于您的两个示例:
> fun_tst(x = 1:1e3, FUN = sum)
[1] "Executing function sum from package base"
[1] 500500
> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
[1] "Executing function glimpse from package dplyr"
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
然而,如所写,它会认为全局环境中的所有函数都来自 base
,即使它们是用户定义的或通过 library
调用引入的。如果这是您的用例,请不要明确说明 "from package base".
如果您使用 deparse()
和 substitute
,您将获得所需的输出,请参阅将变量名称传递给 plot()
、[=16= 时类似的 post ].
fun_tst <- function(x = 1:100, FUN = mean) {
message(paste("Executing function",deparse(substitute(FUN))))
return((FUN(x)))
}
> fun_tst(x = 1:1e3, FUN = sum)
Executing function sum
[1] 500500
> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
Executing function dplyr::glimpse
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
如果您希望将消息作为字符向量,请将 message
替换为 print
。