Function Composition in R (And High Level Functions)

Function Composition in R (and high level functions)

You may make compositing function like this:

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)

or make operator of this.

About the second point, there are lots of such; I think the most used are the *apply family (sapply, mapply, tapply, lapply, apply...).

Function composition assigned to %@% operator in R

I don't know whether it is appropriate, but my first intention would be the following:

`%@%` <- function(f,g) {
if(is.function(f) && is.function(g)) {
#both functions, composition as usual
return(function(...) {f(g(...))} )
}
if(!is.function(f)) {
#f is no function, hence a constant value, return it.
return(f)
}
if(is.function(f) && !is.function(g)) {
#f is function, g not, hence g is the argumemnt to f
return(f(g))
}
}

Some test:

sq <- function(x) x^2
sq %@% sq %@% 5 #625
base::identity %@% base::identity %@% 5 #5
exp %@% log %@% 5 #5
5 %@% sin #5

tanh %@% exp %@% abs %@% sin %@% -pi/4 #0.1903985

A function within a function in the R language

Using the accepted answer in another post, just use Reduce to create the composition, g.

composite <- function(g, h) {function(...)g(h(...))}
g <- Reduce(composite, list(f, f, f, f, f))

g(2)
f(f(f(f(f(2)))))

identical(g(2), f(f(f(f(f(2))))))
#[1] TRUE

How can I write a recursive compose function in R?

1) Try this:

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

1a) A variation of (1) which uses Recall is:

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

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

2) Here is another implementation:

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

3) This implementation is closer to the code in the question. It makes use of of defined in the question:

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

How to do Higher Order Composition in Rust?

In Rust, currying is hard. The strict type system, lifetimes, and nested impl traits not existing all conspire to ruin your day when you try. However, it is possible to create a macro to curry functions, and I did so for code golf at one point. The ungolfed version is here:

macro_rules! curry{
(
$f:ident
$(
($args:ident : $types:ty)
)*
) => {
$(move |$args: $types|)*
$f(
$($args),*
)
}
}

This matches on expressions of the form name(arg1, type1)(arg2, type2)...(argN, typeN) and returns a chain of move closures leading to the function call. Most of the time, however, you can just use _ for the type and let inference figure it out. Using it with compose is simple:

let inc = |x| x as u32 + 1;
let double = |x| x * 2;
let curried = curry!(compose(f: _)(g: _));
assert_eq!(curried(inc)(double)(7), 16);

The code generated by the macro, in this case, looks like this:

move |f: _| move |g: _| compose(f, g)

It simply takes the supplied name and type and pastes it into the closure heads, so you can use it to force arguments for generic functions into concrete types.
Playground

N times function composition

You are on the right path. Based on the requirements, I would try to start from those equations:

compunere 1 f x == f x

The above says that applying f once to x is exactly the same as doing (f x).

compunere 2 f x == f (f x)

Likewise, applying f twice should compute f (f x). If you replace (f x) by a call to compunere, you have:

compunere 2 f x == f (f x) = f (compunere 1 f x)

The general pattern of recursion seems to be:

compunere n f x == f (compunere (n - 1) f x)

Note that the most general type of f is a -> b, but when f is called again with a value of type b, that means that a and b should be the same type, and so f really is an endomorphism, a function of type a -> a. That is the case for N >= 1, but in degenerate case of N=0, you could have a different behaviour.

Applying f zero time to x could mean "return x", which means that compunere could theoretically return a value of type a for zero, for any f being a a -> b function, a and b possibly distinct; you could distinguish both cases with more code, but here we can simply let the typechecker enforce the constraint that a = b in all cases and have an uniform behaviour. You can also make 0 invalid (like negative numbers) by throwing an exception (negative applications could theoretically be postitive applications of the inverse function, but you cannot compute that when knowing nothing about f; f could be non-invertible).

Your code is a little bit different:

compunere 3 f x == (compunere 2 f (f x))
== (compunere 1 f (f (f x)))
== (compunere 0 f (f (f (f x))))
...

The advantage of your approach is that the recursive call to compunere is directly giving the result for the current computation: it is in tail position which allows the compiler to perform tail-call elimination.

When you reach N=0, the value locally bound x gives the result you want. Here, for N=0 as an input, the only natural interpretation is also to return x.

Scheme function that return composition of functions

A clean solution would be

(define (comp-func . procs)
(define (comp-rec arg procs)
(if (null? procs)
arg
((car procs) (comp-rec arg (cdr procs)))))

comp-rec)

However with this solution you need to call it like this ((comp-func f g h) 1 (list f g h)).

Here is a solution that will work if you call it like in your examples, however it is a bit uglier because we need to use set! to change procs argument.

(define (comp-func . procs)
(define (comp-rec arg)
(if (null? procs)
arg
(let ((proc (car procs))
(rest (cdr procs)))
(set! procs rest)
(proc (comp-rec arg)))))

comp-rec)


Related Topics



Leave a reply



Submit