如何在R中编写递归撰写函数?

Ale*_*ian 12 functional-programming r function-composition

我想在R中创建一个函数"compose",它将构成作为参数给出的任意数量的函数.

到目前为止,我已经通过定义一个函数"of"来完成这个,该函数组成两个参数,然后减少这个:

of <- function(f,g) function(x) f(g(x))
id <- function(x) x

compose <- function(...) {
  argms = c(...)
  Reduce(of,argms,id)
}
Run Code Online (Sandbox Code Playgroud)

这似乎工作得很好,但是因为我正在学习R,我以为我会尝试用一种明确的递归方式来编写它,即放弃使用Reduce,这就像你在Scheme中做的那样:

(define (compose . args)
  (if (null? args) identity
      ((car args) (apply compose (cdr args)))))
Run Code Online (Sandbox Code Playgroud)

我遇到了许多障碍,目前主要的障碍似乎是论证的第一个要素没有被认为是一种功能.到目前为止我的弱尝试:

comp <- function(...) {
  argms <- list(...)
  len <- length(argms)
  if(len==0) { return(id) }
  else {
    (argms[1])(do.call(comp,argms[2:len])) 
  }
}
Run Code Online (Sandbox Code Playgroud)

吐出: Error in comp(sin, cos, tan) : attempt to apply non-function

必须有某种方法可以做到这一点,这使我望而却步.有什么建议?

G. *_*eck 12

1)试试这个:

comp1 <- function(f, ...) {
  if (missing(f)) identity
  else function(x) f(comp1(...)(x))
}


# test

comp1(sin, cos, tan)(pi/4)
## [1] 0.5143953

# compose is defined in the question
compose(sin, cos, tan)(pi/4)
## [1] 0.5143953

functional::Compose(tan, cos, sin)(pi/4)
## [1] 0.5143953

sin(cos(tan(pi/4)))
## [1] 0.5143953

library(magrittr)
(pi/4) %>% tan %>% cos %>% sin
## [1] 0.5143953

(. %>% tan %>% cos %>% sin)(pi/4)
## [1] 0.5143953
Run Code Online (Sandbox Code Playgroud)

1a)(1)的变形使用的Recall是:

comp1a <- function(f, ...) {
  if (missing(f)) identity
  else {
    fun <- Recall(...)
    function(x) f(fun(x))
  }
}

comp1a(sin, cos, tan)(pi/4)
## [1] 0.5143953
Run Code Online (Sandbox Code Playgroud)

2)这是另一个实现:

comp2 <- function(f, g, ...) {
  if (missing(f)) identity
  else if (missing(g)) f
  else Recall(function(x) f(g(x)), ...)
}

comp2(sin, cos, tan)(pi/4)
## [1] 0.5143953
Run Code Online (Sandbox Code Playgroud)

3)此实现更接近问题中的代码.它利用of了问题中的定义:

comp3 <- function(...) {
  if(...length() == 0) identity
  else of(..1, do.call("comp3", list(...)[-1]))
}
comp3(sin, cos, tan)(pi/4)
## [1] 0.5143953
Run Code Online (Sandbox Code Playgroud)