2

I have a question which is an extension of another question.

I am wanting to be able to pipeline anonymous functions. In the previous question the answer to pipeline defined functions was to create a pipeline operator "%|>%" and to define it this way:

"%|>%" <- function(fun1, fun2){
              function(x){fun2(fun1(x))}
}

This would allow you to call a series of functions while continually passing the result of the previous function to the next. The caveat was that the functions to to be predefined. Now I'm trying to figure how to do this with anonymous functions. The previous solution which used predefined functions looks like this:

square <- function(x){x^2}
add5 <- function(x){x + 5}

pipelineTest <-
  square %|>%
  add5

Which gives you this behviour:

> pipelineTest(1:10)
 [1]   6   9  14  21  30  41  54  69  86 105

I would like to be able to define the pipelineTest function with anonymous functions like this:

anonymousPipelineTest <-
  function(x){x^2} %|>%
  function(x){x+5} %|>%
  x

When I try to call this with the same arguments as above I get the following:

> anonymousPipelineTest(1:10)
function(x){fun2(fun1(x))}
<environment: 0x000000000ba1c468>

What I'm hoping to get is the same result as pipelineTest(1:10). I know that this is a trivial example. What I'm really trying to get at is a way to pipeline anonymous functions. Thanks for the help!

Community
  • 1
  • 1
Matthew Crews
  • 4,105
  • 7
  • 33
  • 57
  • The last question was an interesting exercise but really this isn't the 'R way' to do things. Is there a reason you don't want to do things the way that [Seth suggested](http://stackoverflow.com/a/13354145/1003565) in the previous question? – Dason Nov 17 '12 at 18:15
  • I am aware that this in not the 'R way' and I'm sorry if this is causing frustration for people. I am coming from F# which makes extensive use of the pipeline operator '|>' for performing a series functions on a set of data. I found this to be exceedingly useful and very clear syntactically. Again, I'm sorry if I am asking how to "put a round peg in a square hole". The first question came from an ignorance of R, now I am looking for the limits of R's flexibility. Thanks to all who help with this question! – Matthew Crews Nov 17 '12 at 18:50

3 Answers3

4

Using Compose, and calling the resulting function gives this:

"%|>%" <- function(...) Compose(...)()

Now get rid of the 'x' as the final "function" (replaced with an actual function, that is not needed but here for example):

anonymousPipelineTest <-
     function(x){x^2} %|>%
     function(x){x+5} %|>% function(x){x}
anonymousPipelineTest(1:10)

[1]   6   9  14  21  30  41  54  69  86 105
Matthew Lundberg
  • 42,009
  • 6
  • 90
  • 112
0

This is an application of an example offered on the ?funprog help page:

Funcall <- function(f, ...) f(...)
anonymousPipelineTest <- function(x) Reduce( Funcall, list(
    function(x){x+5}, function(x){x^2}), 
    x, right=TRUE)
 anonymousPipelineTest(1:10)
 #[1]   6   9  14  21  30  41  54  69  86 105
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • Sure but you could just as easily just use `Compose` couldn't you? `anonyPipeTest <- Compose(function(x){x^2}, function(x){x+5})` I personally don't see why they don't just do things the more natural 'R way' but I'm still interested in an answer to the original question - how do you get the binary operator to work in a situation with anonymous functions? – Dason Nov 17 '12 at 18:27
  • I (now) see that Wallhood is ignoring @mnel's answer which is essentially what I independently constructed. – IRTFM Nov 17 '12 at 18:29
  • This result differs from the OP. This answer is applying the functions in the opposite order from the OP (he squares, then adds 5). – Matthew Lundberg Nov 17 '12 at 18:50
0

I am putting up an answer which is the closest thing I've found for other people looking for the same thing. I won't give myself point for the answer though because it is not what I am wanting.

Returning a Function: If you want to put several functions together the easiest thing I've found is to use the 'Compose' function found in the 'Functional' package for R. It would look something like this:

anonymousPipe <- Compose(
  function(x){x^2},
  function(x){x+5})

This allows you to call this series of functions like this:

> anonymousPipe(1:10)
 [1]   6   9  14  21  30  41  54  69  86 105

Returning Data: If all you want to do is start with some data and send it through a series of transformations (my original intent) then the first function in the 'Compose' function should be your starting data and after the close of the 'Compose' function add a parenthesis pair to call the function. It looks like this:

anonymousPipeData <- Compose(
  seq(1:10),
  function(x){x^2},
  function(x){x+5})()

'anonymousPipeData' is now the data which is a result of the series of functions. Please note the pair of parenthesis at the end. This is what causes R to return the data rather than a function.

Matthew Crews
  • 4,105
  • 7
  • 33
  • 57