R6 传递一个 self$FUN 作为参数
R6 pass a self$FUN as parameter
我正在开始构建一个“用户友好”的 R6 class 并希望让一个函数完成我 class 的大部分工作。这是我目前的结构
x <- X$new()
veggie_cubes <- veggie %>% x$cubesX(ID)
veggie_slices <- veggie %>% x$sliceX(ID)
我现在的问题是是否可以重写代码:
x <- X$new()
veggie_cubes <- veggie %>% x$cutX(cubesX, ID)
veggie_slices <- veggie %>% x$cutX(sliceX, ID)
函数头应该看起来像:cut(.data, FUN, KEY)
到目前为止,我的想法是 cut
像这样写:
cutX= function(.data, FUN, KEY)
{
.data %>%
FUN({{ KEY }}) %>%
base::return()
}
唯一可行的方法是调用 veggie %>% x$cutX(x$cubesX, ID)
,我不太喜欢将其作为“用户友好”的解决方案,我也不太喜欢为此使用字符串。有没有办法不用 x$
来写呢?
这里是简化的 R6 class:
X <- R6::R6Class(
classname = "X",
public = base::list(
cubesX = function(.data, KEY)
{
.data %>%
dplyr::select(!{{ KEY }}) %>%
base::return()
},
sliceX = function(.data, KEY)
{
.data %>%
dplyr::select({{ KEY }}) %>%
base::return()
},
cutX = function(.data, FUN, KEY)
{
.data %>%
FUN( {{ KEY}}) %>%
base::return()
}
)
)
运行 例子:
x <- X$new()
iris %>% x$sliceX(Species)
iris %>% x$cubesX(Species)
# with FUN
iris %>% x$cutX(x$sliceX, Species)
iris %>% x$cutX(x$cubesX, Species)
不是运行:
iris %>% x$cutX(sliceX, Species)
iris %>% x$cutX(cubesX, Species)
提前致谢:-)
以下实现将允许您通过三种方法中的任何一种调用您的函数。它通过使用 non-standard 评估来确定 FUN
是格式 x$func
还是只是一个裸露的 func
。在任何一种情况下,它都采用裸函数名称并构建调用以将其转换为 self$func
。然后它只计算该函数。
因此,以下 R6 class 在所有测试示例中都按预期工作:
X <- R6::R6Class(
classname = "X",
public = base::list(
cubesX = function(.data, KEY)
{
.data %>%
dplyr::select(!{{ KEY }}) %>%
base::return()
},
sliceX = function(.data, KEY)
{
.data %>%
dplyr::select({{ KEY }}) %>%
base::return()
},
cutX = function(.data, FUN, KEY)
{
if(is.call(substitute(FUN))) {
FUN <- substitute(FUN)
FUN[[2]] <- quote(self)
}
else
FUN <- as.call(list(quote(`$`), quote(self), substitute(FUN)))
eval(as.call(list(FUN, quote(.data), substitute(KEY))))
}
)
)
因此,例如:
x <- X$new()
iris %>% x$cutX(sliceX, Species)
#> Species
#> 1 setosa
#> 2 setosa
#> 3 setosa
#> 4 setosa
#> 5 setosa
#> 6 setosa
#> 7 setosa
#> 8 setosa
#> 9 setosa
#> 10 setosa
#> 11 setosa
#> 12 setosa
#> 13 setosa
#> 14 setosa
#> 15 setosa
#> 16 setosa
#> 17 setosa
#> 18 setosa
#> 19 setosa
#> 20 setosa
#> ...etc
我正在开始构建一个“用户友好”的 R6 class 并希望让一个函数完成我 class 的大部分工作。这是我目前的结构
x <- X$new()
veggie_cubes <- veggie %>% x$cubesX(ID)
veggie_slices <- veggie %>% x$sliceX(ID)
我现在的问题是是否可以重写代码:
x <- X$new()
veggie_cubes <- veggie %>% x$cutX(cubesX, ID)
veggie_slices <- veggie %>% x$cutX(sliceX, ID)
函数头应该看起来像:cut(.data, FUN, KEY)
到目前为止,我的想法是 cut
像这样写:
cutX= function(.data, FUN, KEY)
{
.data %>%
FUN({{ KEY }}) %>%
base::return()
}
唯一可行的方法是调用 veggie %>% x$cutX(x$cubesX, ID)
,我不太喜欢将其作为“用户友好”的解决方案,我也不太喜欢为此使用字符串。有没有办法不用 x$
来写呢?
这里是简化的 R6 class:
X <- R6::R6Class(
classname = "X",
public = base::list(
cubesX = function(.data, KEY)
{
.data %>%
dplyr::select(!{{ KEY }}) %>%
base::return()
},
sliceX = function(.data, KEY)
{
.data %>%
dplyr::select({{ KEY }}) %>%
base::return()
},
cutX = function(.data, FUN, KEY)
{
.data %>%
FUN( {{ KEY}}) %>%
base::return()
}
)
)
运行 例子:
x <- X$new()
iris %>% x$sliceX(Species)
iris %>% x$cubesX(Species)
# with FUN
iris %>% x$cutX(x$sliceX, Species)
iris %>% x$cutX(x$cubesX, Species)
不是运行:
iris %>% x$cutX(sliceX, Species)
iris %>% x$cutX(cubesX, Species)
提前致谢:-)
以下实现将允许您通过三种方法中的任何一种调用您的函数。它通过使用 non-standard 评估来确定 FUN
是格式 x$func
还是只是一个裸露的 func
。在任何一种情况下,它都采用裸函数名称并构建调用以将其转换为 self$func
。然后它只计算该函数。
因此,以下 R6 class 在所有测试示例中都按预期工作:
X <- R6::R6Class(
classname = "X",
public = base::list(
cubesX = function(.data, KEY)
{
.data %>%
dplyr::select(!{{ KEY }}) %>%
base::return()
},
sliceX = function(.data, KEY)
{
.data %>%
dplyr::select({{ KEY }}) %>%
base::return()
},
cutX = function(.data, FUN, KEY)
{
if(is.call(substitute(FUN))) {
FUN <- substitute(FUN)
FUN[[2]] <- quote(self)
}
else
FUN <- as.call(list(quote(`$`), quote(self), substitute(FUN)))
eval(as.call(list(FUN, quote(.data), substitute(KEY))))
}
)
)
因此,例如:
x <- X$new()
iris %>% x$cutX(sliceX, Species)
#> Species
#> 1 setosa
#> 2 setosa
#> 3 setosa
#> 4 setosa
#> 5 setosa
#> 6 setosa
#> 7 setosa
#> 8 setosa
#> 9 setosa
#> 10 setosa
#> 11 setosa
#> 12 setosa
#> 13 setosa
#> 14 setosa
#> 15 setosa
#> 16 setosa
#> 17 setosa
#> 18 setosa
#> 19 setosa
#> 20 setosa
#> ...etc