如何将参数(名称)传递给函数工厂?

时间:2017-03-09 12:22:40

标签: r functional-programming closures factory

我需要构建许多具有许多不同参数的函数,尽管它们共享很多代码和结构。 为了避免重复,我认为我很聪明并且自己建立一个功能工厂(也就是封闭)。

我无法弄清楚如何在函数工厂中传递函数参数

我的用例是一堆S3构造函数,它们共享相同的验证机制。 因此,我将以此为例来解释我的问题。

说,我有一个ClassAClassB,每个都需要在各自的构造函数中有自己的参数:

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)
}

显然,我喜欢避免构造函数的 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)  # 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
  }
}

然而,这不起作用,因为结果构造函数只有class_specific_arguments - 参数,而不是实际的A_arg1A_arg2

有办法做到这一点吗? 我做错了吗?

(对我来说非常重要的是,生成的类构造函数具有正确命名的参数,因此...方法无法工作)。

1 个答案:

答案 0 :(得分:1)

这是我的尝试:

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"

来自this questionas.list(environment())的提示。请注意,您应该在该路径上格外小心,正如?formals所说,&#34;这是 先进的,危险的编码&#34;。