tidyverse / magrittr

Improve the readability of R code with the pipe
https://magrittr.tidyverse.org
Other
957 stars 157 forks source link

combination of fseqs #235

Closed MyKo101 closed 3 years ago

MyKo101 commented 3 years ago

I believe the ability to add fseq functions together as a chain would be useful to users of fseq functions and would probably increase their usage. For example, users could define the following:

f <- . %>% add(2) %>% divide_by(2)
g <- . %>% multiply_by(2)
h <- f + g

Which would output:

> h
Functional sequence with the following components:

 1. add(., 2)
 2. multiply_by(., 2)
 3. divide_by(., 2)

Use 'functions' to extract the individual functions. 

I had implemented a feature like this in my own package, mpipe, however the magrittr 2.0 update broke my version and I've not got round to updating it on GH. I would be interested to know if this feature would be appealing to be used directly in magrittr.

I had a look at the new fseq internals and believe that it could be as simple as the follow method:

`+.fseq` <- function(a,b){
  a_env <- environment(a)
  b_env <- environment(b)

  e <- new.env(parent = parent.env(a_env))
  e[["env"]] <- a_env
  e[["_function_list"]] <- c(
    a_env[["_function_list"]],
    b_env[["_function_list"]]
  )
  e[["exprs"]] <- as.pairlist(c(
    a_env[["exprs"]],
    b_env[["exprs"]]
  ))
  res <- function(value){
    freduce(value,`_function_list`)
  }
  environment(res) <- e
  class(res) <- c("fseq","function")
  res
}

However, I understand if this is out of scope for magrittr

lionel- commented 3 years ago

I see that mpipe is still a github-only package. Just a heads up that it shouldn't be published on CRAN because it defines methods for:

Method registration has global effects for the whole package ecosystem as soon as the package is loaded, even if it's only loaded because of indirect dependencies which the user (and other packages) have no idea about. This is why you shouldn't implement methods for others.

I think using purrr to combine fseqs is probably the way to go:

f <- . %>% add(2) %>% divide_by(2)
g <- . %>% multiply_by(2)
h <- purrr::compose(f, g)

h
#> <composed>
#> 1. Functional sequence with the following components:
#>
#>  1. multiply_by(., 2)
#>
#> Use 'functions' to extract the individual functions.
#>
#> 2. Functional sequence with the following components:
#>
#>  1. add(., 2)
#>  2. divide_by(., 2)
#>
#> Use 'functions' to extract the individual functions.

h(10)
#> [1] 11

f(g(10))
#> [1] 11
hadley commented 3 years ago

Just to close the loop here, I think mpipe is a cool idea, but not something we'd consider for inclusion in magrittr, because we're trying to keep it as small as possible as we plan to transition to the base R pipe over the next few years.