使用 rlang 的 enexprs 捕获函数
Posted
技术标签:
【中文标题】使用 rlang 的 enexprs 捕获函数【英文标题】:capturing functions using rlang's enexprs 【发布时间】:2018-08-12 15:09:11 【问题描述】:我正在编写一个函数,以便该函数的调用者可以以声明方式编写模式:
myschema <- Schema(
patientID = character,
temp = numeric,
treated = logical,
reason_treated = factor(levels=c('fever', 'chills', 'nausea'))
)
稍后,我将能够使用此架构中声明的类型来组装数据帧。我认为这项工作的最佳人选是使用rlang
中提供的元编程功能:
Schema = function(...)
schematypes = rlang::enexprs(...)
但是,大多数examples 都与捕获表达式有关,然后将它们用作函数的参数,而不是函数本身。也就是说,我发现很难捕捉到以下表达式的右侧:
patientID = character
然后可以在以后将其评估为character(myvec)
,只要我得到myvec
。这同样适用于以下情况:
reason_treated = factor(levels=c('fever', 'chills', 'nausea'))
我稍后想将其评估为factor(myvec, levels=c('fever', 'chills', 'nausea'))
谢谢!
【问题讨论】:
【参考方案1】:如果我理解正确,您实际上是在用函数构建模式,并且您希望在这些函数可用时将这些函数应用于某些参数。这属于函数式编程而不是rlang
元编程。
purrr::map
及其“引擎”as_mapper
已经捕获了您想要的大部分功能。你可以直接用它来定义
Schema <- function(...) purrr::map( list(...), purrr::as_mapper )
您现在可以按照您的建议使用它来构建新模式(对函数定义进行少量修改):
myschema <- Schema(
patientID = as.character, # Note the correct function name
temp = as.numeric, # Ditto
treated = as.logical, # Tritto
reason_treated = ~factor(., levels=c('fever', 'chills', 'nausea'))
)
# $patientID
# function (x, ...)
# as.character(x = x, ...)
# <environment: base>
#
# $temp
# function (x, ...)
# as.double(x = x, ...)
# <environment: base>
#
# $treated
# function (x, ...)
# as.logical(x = x, ...)
# <environment: base>
#
# $reason_treated
# function (..., .x = ..1, .y = ..2, . = ..1)
# factor(., levels = c("fever", "chills", "nausea"))
# <bytecode: 0x00000000027a2d00>
鉴于您的新架构,可以使用 map
的姊妹函数来注册新患者,该函数将两个列表/向量中的参数对齐:
register_patient <- function(myvec) purrr::map2( myschema, myvec, ~.x(.y) )
JohnDoe <- register_patient( c(1234, 100, TRUE, "fever") )
# $patientID
# [1] "1234"
#
# $temp
# [1] 100
#
# $treated
# [1] TRUE
#
# $reason_treated
# [1] fever
# Levels: fever chills nausea
让我们验证每个元素的类型:
purrr::map( JohnDoe, class )
# $patientID
# [1] "character"
#
# $temp
# [1] "numeric"
#
# $treated
# [1] "logical"
#
# $reason_treated
# [1] "factor"
【讨论】:
以上是关于使用 rlang 的 enexprs 捕获函数的主要内容,如果未能解决你的问题,请参考以下文章
解决载入了名字空间‘rlang’ 0.4.5,但需要的是>= 0.4.6
解决:Error: Insufficient values in manual scale. 5 needed but only 4 provided.Run `rlang::last_error()
Error: stat_count() can only have an x or y aesthetic Run `rlang::last_error()` to see where the err