如何将参数(名称)传递给函数运算符? (无点编程)

时间:2017-08-28 16:34:39

标签: r validation functional-programming closures pointfree

背景

说,我有一个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)
}

我的实际用例有点复杂;我正在尝试使用构造函数和check.ClassName()方法将类型验证变为S3

动机

显然,我希望避免上述构造函数的通用部分中的重复,因此可以像这样使用的函数工厂会很好:

ClassA <- produce_class_constructor(classname = "ClassA", fun = function(A_arg1, A_arg2) {return(list(A_arg1, A_arg2))})

理想情况下,这应该产生与上述手动构造的ClassA函数完全相同的函数,其中一般部分被考虑在内。 (在我的实际用例中的一般部分相当长一点)。

警告:工厂生成的ClassA()构造函数保留参数名称(此处为A_arg1A_arg2)至关重要,以便文档和自动完成可以指导用户进行构建。

我想使用最佳功能编程(FP)实践来解决这个问题。

previously asked关于通过一个简单的闭包来做这件事,但我知道是否想通过function operators这样做可能不是一个更好的方法,我只是换行(或compose)每个类的特定部分周围的一般运算符,以产生每个类的构造函数。

伪代码中,我想设计这样的东西:

produce_class_constructor <- function(classname, fun) {
  class_constructor_func <- validate_class(append_class(classname, fun()))
}

其中,append_class()使自定义fun也附加了某个类,validate_class()反过来也会对其结果进行自定义fun运行检查。

然后我可以使用这个构造函数因子来优雅地创建上面的ClassA()

    ClassA <- produce_class_constructor(classname = "ClassA", fun = function(A_arg1, A_arg2) {return(list(A_arg1, A_arg2))})

尝试

这是我的简单(失败)尝试。

# simple helper to append classes
append_class <- function(obj, classname) {
  class(obj) <- append(class(obj), classname)
  return(obj)
}

produce_class_constructor <- function(classname, fun) {
  force(fun)  # not sure what this does, but seems to be necessary as per http://adv-r.had.co.nz/Function-operators.html

  # all the GENERAL construction magic from above now happens here
  class_constructor_fun <- function(...) {
    append_class(classname, fun(...))
  }
  formals(class_constructor_fun) <- formals(fun)  # this is necessary to carry over argument names

  return(class_constructor_fun)
}

ClassB <- produce_class_constructor(classname = "ClassB", fun = function(B_arg1, B_arg2) {
  # this is the class-SPECIFIC construction magic from above
  out <- B_arg1 + B_arg2
  return(out)
})

ClassB(B_arg1 = 1, B_arg2 = 2)  # this fails

好消息是生成的ClassB()已命名参数。

坏消息是他们没有被传递,整个事情都失败了:

 Error in append(class(obj), classname) : 
  '...' used in an incorrect context 

问题(S)

  1. 这是一个合理的“无点”FP设计,一般都是好的/好主意吗?
  2. 如果是,我该如何解决我的尝试? (=使“内部”函数知道其参数)
  3. 如果没有,那么“适当的”FP方式会是什么?
  4. (额外奖励):那里是否已经有了一个包裹,将这种验证和严谨性转变为S3? (其他OO不是一种选择,可以吓跑我的裤子。)

0 个答案:

没有答案