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)
| 归档时间: |
|
| 查看次数: |
345 次 |
| 最近记录: |