0

我正在编写一个函数,以便该函数的调用者可以以声明方式编写模式:

myschema <- Schema(
  patientID = character,
  temp = numeric,
  treated = logical,
  reason_treated = factor(levels=c('fever', 'chills', 'nausea'))
)

稍后,我将能够使用此模式中声明的类型来组装数据帧。我认为这项工作的最佳人选是使用以下可用的元编程功能rlang

Schema = function(...) {
  schematypes = rlang::enexprs(...)

}

但是,大多数示例都与捕获表达式有关,然后将它们用作函数的参数,而不是用作函数本身。也就是说,我发现很难捕捉到以下表达式的右侧:

patientID = character

然后以后可以在以后评估它character(myvec),只要我得到myvec。这同样适用于以下情况:

reason_treated = factor(levels=c('fever', 'chills', 'nausea'))

我稍后想将其评估为factor(myvec, levels=c('fever', 'chills', 'nausea'))

谢谢!

4

1 回答 1

0

如果我理解正确,您实际上是在用函数构建模式,并且您希望在这些函数可用时将这些函数应用于某些参数。这属于函数式编程而不是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"
于 2018-07-31T05:36:41.307 回答