r - Expand call stored in a variable before passing to function
问题描述
I have a call stored in a variable. If relevant, the call originates from a one-sided formula:
f <- ~ a + b
rhs <- rlang::f_rhs(f)
rhs
#> a + b
Created on 2020-03-19 by the reprex package (v0.3.0)
Now, the formula might contain bquote
-style escaping .()
, and I want to get all the escaped names.
Looking at bquote
's source code, I created this function:
escapedNames <- function (expr, where = parent.frame())
{
unquote <- function(e) {
if (is.pairlist(e)) {
NULL
} else if (length(e) <= 1L) {
NULL
} else if (e[[1L]] == as.name(".")) {
deparse(e[[2L]])
} else {
x <- sapply(e, unquote)
unlist(x)
}
}
unquote(substitute(expr))
}
escapedNames(a + .(b) + c)
#> [1] "b"
As you can see, it works just fine for hard-coded expressions. However, I can't figure out how to pass calls stored in variables.
f <- ~ a + .(b)
rhs <- rlang::f_rhs(f)
escapedNames(rhs)
#> NULL
This makes perfect sense, of course, since escapedNames
treats whatever it is given as the call I want to analyze, so it doesn't know to expand rhs
before looking for names.
So, how can I solve this?
解决方案
发布赏金后,我立即想出了一个方法,但请告诉我一个更好的方法!
我们可以在评估之前使用eval
andrlang::expr
来强制扩展公式变量escapedNames
:
escapedNames <- function (expr)
{
unquote <- function(e) {
if (is.pairlist(e) || length(e) <= 1L) NULL
else if (e[[1L]] == as.name(".")) deparse(e[[2L]])
else unlist(sapply(e, unquote))
}
unquote(substitute(expr))
}
formula <- ~ a + .(b) + c + .(d)
rhs <- rlang::f_rhs(formula)
eval(rlang::expr(escapedNames(!!rhs)))
#> [1] "b" "d"
由reprex 包(v0.3.0)于 2020-03-23 创建
推荐阅读
- linux - 如何在不配对的情况下读取 BLE 广告包
- python - 如何根据条件 if-then 语句将变量设置为零?
- django - 如何仅将子域关联到我在 Digital Ocean 上的 Django 应用程序?
- svelte - 使用 svelte/store 更新方法更新对象时是否应该使用扩展运算符?
- visual-studio - 如何在 Visual Studio C# 中过滤 Intellisense、自动完成功能,以仅显示项目定义的成员?
- javascript - 我的没有日期方法的 JS 时钟不起作用
- mysql - 输出来自同一个 SQL 表的不同列的不同行
- grammar - 所有字符串 X2Y,其中 X 和 Y 由 0 和 1 组成且 X ≠ Y
- c++ - 使用 std::atomic 标志和 std::condition_variable 等待工作线程
- uuid - 客户端提供的与服务器生成的 api 服务的 id