R中有类似函数合成的东西吗?
我认为在haskell中它有点像“(.)”,而在agda中它是环运算符。
Also, I find litte information on high level functional programming in R. I found the Functions "Reduce", "Map", "Filter"..., are there more? Any pointers?
R中有类似函数合成的东西吗?
我认为在haskell中它有点像“(.)”,而在agda中它是环运算符。
Also, I find litte information on high level functional programming in R. I found the Functions "Reduce", "Map", "Filter"..., are there more? Any pointers?
您可以使合成功能如下:
composite<-function(f,g) function(...) f(g(...))
f<-function(x) x+1;
g<-function(x) x*2;
composite(f,g)(7)
composite(g,f)(7)
或者使其成为操作者。
关于第二点,有很多这样的;我认为最常用的是*apply系列(sapply、mapply、tapply、lapply、apply…)。
函数
包具有Compose
函数,该函数可概括为任意数量的函数:
set.seed(123)
x <- matrix(runif(100), 10, 10)
mean(rowSums(scale(x)))
# [1] 5.486063e-18
library(functional)
Compose(scale, rowSums, mean)(x)
# [1] 5.486063e-18
(请注意,这些功能是从左到右应用的。)
现在purrr库中有一个compose函数。默认情况下,合成是从右到左进行的,如Haskell中所示,但可以使用.dir参数反转:
library(purrr)
f = function(x) x+1
g = function(x) x*3
> compose(g,f)(1)
[1] 6
> compose(f,g, .dir="forward")(1)
[1] 6
我想回答第一个问题。可以定义R组合运算符%.%代码>那个
ls
act normally.该运算符的灵感来自R4.1<code>pipeOp</code>运算符<code>|>代码>。以下是预期结果:
## example component functions
ff <- function(n, a=1.0) 1:n*a
gg <- function(x, b=0.5) x^b
hh <- function(x, c=2.0, d=0.5) d * log(x, c)
## composition #1, rotate `c` in hh()
(tmp <- ff(a=1) %.% gg(b=2) %.% hh(x=3, d=1) %.% round(digits=3))
# function (...)
# round(hh(gg(ff(..., a = 1), b = 2), x = 3, d = 1), digits = 3)
tmp(9)
# [1] Inf 0.792 0.500 0.396 0.341 0.307 0.282 0.264 0.250
## composition #3: a component function is environment sensitive.
(ls() %.% grep(pattern="^[a-z]", value=TRUE) %.% toupper)(environment())
# [1] "FF" "GG" "HH" "TMP"
这是%.%的定义代码>:
"%.%" <- function(f, g, .dp=0)
{
f <- substitute(f)
g <- substitute(g)
## treatment of f()
if("%.%" == all.names(f)[1])
{
## f() is a %.% expression, expand it by a deeper call of %.%.
f <- eval(as.call(append(as.list(f), c(.dp=.dp+1))))
}
else
{
## f() is the deepest function, (i.e., the left most syntax of
## a %.% chain), insert ... as its first argument.
f <- as.call(append(as.list(f), quote(...), 1L))
}
## expands g() to g(f(...)) by treating f(...) as the 1st argument
g <- as.call(append(as.list(g), f, 1L))
## pack up and return
if(.dp > 0)
{
ret <- g # a deeper call of %.% return expanded expression
}
else
{
## the top call of %.% build a function enclosing g(f(...))
ret <- function(...) {}
body(ret) <- g
## treat the function as if it was defined from outside.
environment(ret) <- parent.frame()
}
ret
}
## example component functions
ff <- function(n, a=1.0) 1:n*a
gg <- function(x, b=0.5) x^b
hh <- function(x, c=2.0, d=0.5) d * log(x, c)
## composition #1, rotate `c` in hh()
(tmp <- ff(a=1) %.% gg(b=2) %.% hh(x=3, d=1) %.% round(digits=3))
# function (...)
# round(hh(gg(ff(..., a = 1), b = 2), x = 3, d = 1), digits = 3)
tmp(9)
# [1] Inf 0.792 0.500 0.396 0.341 0.307 0.282 0.264 0.250
## composition #2: rotate `x` in hh(); compose an anonymous function.
sapply(1:4, ff(a=1) %.% gg(b=2) %.% hh(d=1, c=2) %.% round(digits=3))
# [[1]]
# [1] 0
#
# [[2]]
# [1] 0 2
#
# [[3]]
# [1] 0.00 2.00 3.17
#
# [[4]]
# [1] 0.00 2.00 3.17 4.00
## composition #3: a component function is environment sensitive.
(ls() %.% grep(pattern="^[a-z]", value=TRUE) %.% toupper)(environment())
# [1] "FF" "GG" "HH" "TMP"
## does not show `f`, `g` and `ret` (and `.dp`) as if the composition
## is outside of `%.%` s environment.
## composition #4: example from Answer #1 by [flodel]
set.seed(123)
x <- matrix(runif(100), 10, 10)
mean(rowSums(scale(x)))
# [1] 5.486063e-18
(scale %.% rowSums %.% mean)(x)
# [1] 5.486063e-18
目前,我无法获得空参数列表来处理函数体中缺少语法的
允许空白参数的函数,因此我必须将
environment()
作为参数传递给ls
和grep
的组合(示例#3),尽管ls
允许空参数。
值得一提的是,这里有一个以R(>;=4.1.0)为基的线性函数,使用Reduce
来组成任意数量的函数,这里的scale
、rowSums
和mean
。
mean(rowSums(scale(mtcars))) # nested function call
f <- Reduce((g, h) {(x) h(g(x))}, list(scale, rowSums, mean))
f(mtcars) # now, calling f gives same result as nested call above
这或多或少就是functional::Compose
所做的。
注意事项:
is shorthand for function
as of R 4.1.0purrr::compose
is more readable and flexible and does much more under the hood.I m trying my hand at Euler Problem 4 in Haskell. It asks for that largest palindrome formed by multiplying two three-digit numbers. The problem was simple enough, and I thought my Haskell-fu was up ...
Can anybody explain how does foldr work? Take these examples: Prelude> foldr (-) 54 [10, 11] 53 Prelude> foldr (x y -> (x+y)/2) 54 [12, 4, 10, 6] 12.0 I am confused about these executions....
How can I efficiently implement a list data structure where I can have 2 views to the head and end of the list, that always point to a head a tail of a list without expensive calls to reverse. i.e: ...
I am doing problem 61 at project Euler and came up with the following code (to test the case they give): p3 n = n*(n+1) `div` 2 p4 n = n*n p5 n = n*(3*n -1) `div` 2 p6 n = n*(2*n -1) p7 n = n*(5*n -3)...
I ve just started learning about Functional Programming, using Haskel. I m slowly getting through Erik Meijer s lectures on Channel 9 (I ve watched the first 4 so far) and in the 4th video Erik ...
The type of the Prelude function flip is: flip :: (a -> b -> c) -> b -> a -> c I.e., it takes one binary function and two arguments. The type of the Prelude function id is: id :: a -...
group :: Ord a => [(a, [b])] -> [(a, [b])] I want to look up all pairs that have the same fst, and merge them, by appending all the list of bs together where they have the same a and discarding ...
I want to do a popen() / python s subprocess.communicate from Haskell - start a program, give it stdin, and get its stdout/stderr. What s the most direct / Haskellish way to do this?