将参数传递给Compose'd函数?

Ari*_*man 4 functional-programming r

我有一种情况,我想将参数传递给通过链接的函数Compose.我意识到我可以在参数中使用Curry,但我希望得到的函数比这更灵活.这是一个简单的测试用例来显示问题:

> library(functional)
> f <- function(x, scale) x^2*scale
> g <- function(y, shift) sqrt(y)+shift
> h <- Compose(f,g)
> h(1)
Error in x^2 * scale : 'scale' is missing
> h(1, scale=1, shift=0)
Error in Reduce(function(x, f) f(x), fs, ...) : 
  unused argument(s) (scale = 1, shift = 0)
Run Code Online (Sandbox Code Playgroud)

有没有办法使用Compose它允许结果函数在被调用时仍然允许参数? ?Compose除了作为可爱键盘的挽歌之外,它不是很有用.

Bri*_*ggs 6

由于函数组合是在计算机科学中制定的,因此所有函数只有一个参数.该Composition函数也假设了这一点.Currying是解决这个问题的典型方法.另外一个复杂因素是必须将任何其他命名参数传递给合成过程中的正确函数.

以下是几种方法:

h1 <- function(scale, shift)
  Compose(Curry(f,scale), Curry(g,shift))
Run Code Online (Sandbox Code Playgroud)

h1获取命名参数并使用正确的curried创建组合函数.返回是1参数函数:

> h1(scale=1, shift=0)(1)
[1] 1
Run Code Online (Sandbox Code Playgroud)

另一种方法是延迟咖喱(以及因此组成)直到实际功能评估.在这种情况下,原始的"Compose"函数只是设置所有内容,但实际上并不构成,返回一个curry,composes和evaluate的函数.

ComposeDelayedCurry <- function(...) {
  fs <- list(...)
  all.formals <- lapply(fs, formals)
  function(...) {
    local.args <- list(...)
    pos.args <- lapply(all.formals, function(f) {
      local.args[names(f)[[-1]]]
    })
    curried <- lapply(seq_along(fs), function(i) {
      do.call(Curry, c(fs[[i]], pos.args[[i]]))
    })
    do.call(Compose, curried)(..1)
  }
}

h2 <- ComposeDelayedCurry(f,g)
Run Code Online (Sandbox Code Playgroud)

现在打电话h2会在评估时完成所有工作.这做了几个假设.一个是每个函数(和函数调用)的第一个参数是正在组合的函数.第二个是所有其他参数都是命名参数.没有什么可以通过传递给函数....这是因为必须检查每个函数的形式以了解每个参数"去"的位置.我认为这会处理不指定默认值的参数,但我不完全确定.

> h2(1, scale=1, shift=0)
[1] 1
> h2(3, scale=5, shift=2)
[1] 8.708204
> sqrt(5*(3^2))+2
[1] 8.708204
Run Code Online (Sandbox Code Playgroud)