我如何将参数(名称)传递给函数工厂? [英] how can I pass argument (names) to a function factory?
问题描述
我需要构建许多具有许多不同参数的函数,尽管它们共享很多代码和结构。
为了避免重复,我认为自己会很聪明,自己构建一个函数工厂(aka closure)。
我无法弄清楚如何在函数工厂内传递函数参数。
我的用例是一堆S3构造函数,它们共享相同的验证机制。
所以我用这个例子来解释我的问题。
说,我有一个 ClassA
和 ClassB
,它们中的每一个在各自的构造函数中都需要自己的参数:
ClassA < - 函数(A_arg1,A_arg2){
#发生了一些特定类的构造魔术,比如
out < - list(A_arg1,A_arg2)
#some一般建筑魔术发生
class(out)< - ClassA
return(out)
}
ClassB< - 函数(B_arg1,B_arg2){
#一些特定类的建筑魔术发生,比如
out< - B_arg1 + B_arg2
# b班(out)< - ClassB
返回(出)
}
很明显,我很想避免构造函数的 general 部分中的重复,所以可以像一样使用的函数工厂会很好:
ClassA < - produce_class_constructor(classname =ClassA,fun = function(A_arg1,A_arg2){return(list(A_arg1,A_arg2))})
理想情况下,这应该产生与上面手动构建的完全相同的功能 ClassA
函数,并将其中的一般部分分解出来。
这是我在构建函数工厂时的尝试
: produce_class_constructor< - function(classname,fun){
class_specific_arguments< - formals(fun = fun)#这可以在控制台上正常工作
construct_class< - 函数(class_specific_arguments){
#在这里运行特定于类的东西
out< - fun(class_specific_arguments)
#
class(out)< - classname
}
}
然而,这是行不通的,因为结果构造函数只有一个 class_specific_arguments
-argument,而不是实际的 A_arg1
和 A_arg2
。
有没有办法做到这一点?
我是否做错了?
(这对我来说非常重要,因为结果类构造函数具有正确命名的参数,所以
这是我的尝试:
produce_class_constructor< - function(classname,fun){
out_fun< - function(){
out_obj< - do.call(fun,as.list(environment()))
class(out_obj)< - classname
out_obj
}
formals(out_fun)< - formals (fun)
out_fun
}
ClassA < - produce_class_constructor(classname =ClassA,
fun = function(A_arg1,A_arg2){list(A_arg1, A_arg2)})
ClassA(1,2)
#[[1]]
#[1] 1
#
#[[2]]
#attr(,class)
#[1]ClassA
ClassB < - produce_class_constructor(classname =ClassB,
fun = function(B_arg1,B_arg2){B_arg1 + B_arg2})
ClassB(B_arg2 = 2,1)
#[1] 3
#attr(,class)
#[1]ClassB
使用 as.list(environment())
来自这个问题。请注意,您应该特别注意沿着该路径,因为?formals
说,这是
高级危险编码。
I need to build a lot of functions with lots of different arguments, though they otherwise share a lot of code and structure. To avoid duplication, I thought I'd be clever and build myself a function factory (aka closure).
I can't figure out how to pass the function arguments inside the function factory.
My use case is a bunch of S3 constructor functions, all of which share the same validation mechanism. So I'll use that as an example to explain my problem.
Say, I have a ClassA
and ClassB
, each of which require their own arguments in the respective constructor functions:
ClassA <- function(A_arg1, A_arg2) {
# some class-SPECIFIC construction magic happens, say
out <- list(A_arg1, A_arg2)
# some GENERAL construction magic happens
class(out) <- "ClassA"
return(out)
}
ClassB <- function(B_arg1, B_arg2) {
# some class-SPECIFIC construction magic happens, say
out <- B_arg1 + B_arg2
# some GENERAL construction magic happens
class(out) <- "ClassB"
return(out)
}
Obviously, I'd love to avoid the duplication in the general part of the constructor functions, so a function factory that could be used like so would be nice:
ClassA <- produce_class_constructor(classname = "ClassA", fun = function(A_arg1, A_arg2) {return(list(A_arg1, A_arg2))})
This should, ideally, yield the exact same function as the above manually constructed ClassA
function, with the general part factored out.
Here's my attempt at building that function factory:
produce_class_constructor <- function(classname, fun) {
class_specific_arguments <- formals(fun = fun) # this works just fine on the console
construct_class <- function(class_specific_arguments) {
# here runs the class-specific stuff
out <- fun(class_specific_arguments)
# here runs the general stuff
class(out) <- classname
}
}
This however, does not work, because the resulting constructor function only has a class_specific_arguments
-argument, not the, well, actual A_arg1
, and A_arg2
.
Is there way to do this? Am I doing this wrong?
(It's really important to me that the resulting class constructor functions have properly named arguments, so a ...
approach won't work).
Here's my attempt:
produce_class_constructor <- function(classname, fun) {
out_fun <- function() {
out_obj <- do.call(fun, as.list(environment()))
class(out_obj) <- classname
out_obj
}
formals(out_fun) <- formals(fun)
out_fun
}
ClassA <- produce_class_constructor(classname = "ClassA",
fun = function(A_arg1, A_arg2) {list(A_arg1, A_arg2)})
ClassA(1, 2)
#[[1]]
#[1] 1
#
#[[2]]
#[1] 2
#
#attr(,"class")
#[1] "ClassA"
ClassB <- produce_class_constructor(classname = "ClassB",
fun = function(B_arg1, B_arg2) {B_arg1 + B_arg2})
ClassB(B_arg2 = 2, 1)
#[1] 3
#attr(,"class")
#[1] "ClassB"
Idea with as.list(environment())
taken from this question. Note that you should be extra careful along that path, as ?formals
says, "this is
advanced, dangerous coding".
这篇关于我如何将参数(名称)传递给函数工厂?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!