将带引号的字符串放入 rlang 函数中的正确方法是什么?
What is the correct way to put quoted strings in rlang functions?
我正在编写一个函数,我将定期使用它来过滤数据库中的日期和姓名(然后每月对它们执行一些 counting/calculations)。
我想知道在这种情况下,在 rlang
函数中插入和计算字符串的正确方法是什么?
我使用 quo
将字符串放入函数中是否正确?
示例:
business_flights = tibble(passanger_name=rep(c(rep("John RED",3),rep("Mary ORANGE",3)),4),
dep_date=seq(from = lubridate::ymd('2005-04-07'),
to = lubridate::ymd('2025-03-22'), length.out = 24),
flight_num = sample(seq(from = 99, to = 1999, by = 30), size = 24, replace = TRUE))
filter_flights = function(mytibble, name, date0, date1) {
require(tidyverse); require(lubridate)
flights_filtered = mytibble %>%
filter(dep_date >= !!date0, dep_date < !!date1,
grepl(!!name, passanger_name))
View(flights_filtered)
}
filter_flights(mytibble = business_flights,
name = quo("RED"),
date0 = quo("2005-10-13"),
date1 = quo(today()))
非标准计算允许您捕获和操作表达式。在 base R 中,这主要是通过使用 quote
:
来完成的
quote(x)
# x
quote( a*log10(b+5) )
# a * log10(b + 5)
但是,任何由单个文字组成的捕获表达式本身就是该文字:
identical( quote(5), 5 ) # TRUE
identical( quote("a"), "a" ) # TRUE
identical( quote(FALSE), FALSE ) # TRUE
identical( quote(5+5), 10 ) # FALSE, expression is not a single literal
来自 tidyverse 的 rlang::quo
通过捕获表达式和产生该表达式的环境来构建此功能。这些一起定义了一个 quosure:
quo(x)
# <quosure>
# expr: ^x
# env: global
f <- function() {quo(x)}
f()
# <quosure>
# expr: ^x
# env: 0x55b7e61d5c80
将表达式放在它们的环境旁边可以让您确保在它们通过您的代码时始终以一致的方式对其求值:
x <- 5
g <- function( myexpr ) {
x <- 10
eval_tidy( myexpr )
}
x # Evaluate expression directly in its environment
# 5
g( quote(x) ) # Evaluate expression inside g()
# 10
g( quo(x) ) # Evaluate expression in its env, while inside g()
# 5
然而,当捕获一个 quosure 中的文字时,quo
为其分配一个空环境:
quo("x")
# <quosure>
# expr: ^"x"
# env: empty
这是因为字符串 "x"
将始终求值为 "x"
,而不管它在什么环境中求值。因此,几乎没有理由 quo
字符串对象(或与此相关的任何文字)。它什么都不做,正如评论中指出的那样,没有它,您的代码也能正常工作。
我正在编写一个函数,我将定期使用它来过滤数据库中的日期和姓名(然后每月对它们执行一些 counting/calculations)。
我想知道在这种情况下,在 rlang
函数中插入和计算字符串的正确方法是什么?
我使用 quo
将字符串放入函数中是否正确?
示例:
business_flights = tibble(passanger_name=rep(c(rep("John RED",3),rep("Mary ORANGE",3)),4),
dep_date=seq(from = lubridate::ymd('2005-04-07'),
to = lubridate::ymd('2025-03-22'), length.out = 24),
flight_num = sample(seq(from = 99, to = 1999, by = 30), size = 24, replace = TRUE))
filter_flights = function(mytibble, name, date0, date1) {
require(tidyverse); require(lubridate)
flights_filtered = mytibble %>%
filter(dep_date >= !!date0, dep_date < !!date1,
grepl(!!name, passanger_name))
View(flights_filtered)
}
filter_flights(mytibble = business_flights,
name = quo("RED"),
date0 = quo("2005-10-13"),
date1 = quo(today()))
非标准计算允许您捕获和操作表达式。在 base R 中,这主要是通过使用 quote
:
quote(x)
# x
quote( a*log10(b+5) )
# a * log10(b + 5)
但是,任何由单个文字组成的捕获表达式本身就是该文字:
identical( quote(5), 5 ) # TRUE
identical( quote("a"), "a" ) # TRUE
identical( quote(FALSE), FALSE ) # TRUE
identical( quote(5+5), 10 ) # FALSE, expression is not a single literal
来自 tidyverse 的 rlang::quo
通过捕获表达式和产生该表达式的环境来构建此功能。这些一起定义了一个 quosure:
quo(x)
# <quosure>
# expr: ^x
# env: global
f <- function() {quo(x)}
f()
# <quosure>
# expr: ^x
# env: 0x55b7e61d5c80
将表达式放在它们的环境旁边可以让您确保在它们通过您的代码时始终以一致的方式对其求值:
x <- 5
g <- function( myexpr ) {
x <- 10
eval_tidy( myexpr )
}
x # Evaluate expression directly in its environment
# 5
g( quote(x) ) # Evaluate expression inside g()
# 10
g( quo(x) ) # Evaluate expression in its env, while inside g()
# 5
然而,当捕获一个 quosure 中的文字时,quo
为其分配一个空环境:
quo("x")
# <quosure>
# expr: ^"x"
# env: empty
这是因为字符串 "x"
将始终求值为 "x"
,而不管它在什么环境中求值。因此,几乎没有理由 quo
字符串对象(或与此相关的任何文字)。它什么都不做,正如评论中指出的那样,没有它,您的代码也能正常工作。