Dear R-devel, The most popular piping operator sits in the package `magrittr` and is used by a huge amount of users, and imported /reexported by more and more packages too. Many workflows don't even make much sense without pipes nowadays, so the examples in the doc will use pipes, as do the README, vignettes etc. I believe base R could have a piping operator so packages can use a pipe in their code or doc and stay dependency free. I don't suggest an operator based on complex heuristics, instead I suggest a very simple and fast one (>10 times than magrittr in my tests) : `%.%` <- function (e1, e2) { eval(substitute(e2), envir = list(. = e1), enclos = parent.frame()) } iris %.% head(.) %.% dim(.) #> [1] 6 5 The difference with magrittr is that the dots must all be explicit (which sits with the choice of the name), and that special magrittr features such as assignment in place and building functions with `. %>% head() %>% dim()` are not supported. Edge cases are not surprising: ``` x <- "a" x %.% quote(.) #> . x %.% substitute(.) #> [1] "a" f1 <- function(y) function() eval(quote(y)) f2 <- x %.% f1(.) f2() #> [1] "a" ``` Looking forward for your thoughts on this, Antoine [[alternative HTML version deleted]]
Is there some concrete example of your ?many workflows don?t even make much sense without pipes nowadays? comment? I don?t think I?m opposed to pipes in the absolute, but as I am now deep into my second decade of using R I?ve done just fine without them. As I would guess have the vast majority of users and code that is used throughout the world. Jeff On Sat, Oct 5, 2019 at 09:34 Ant F <antoine.fabri at gmail.com> wrote:> Dear R-devel, > > The most popular piping operator sits in the package `magrittr` and is used > by a huge amount of users, and imported /reexported by more and more > packages too. > > Many workflows don't even make much sense without pipes nowadays, so the > examples in the doc will use pipes, as do the README, vignettes etc. I > believe base R could have a piping operator so packages can use a pipe in > their code or doc and stay dependency free. > > I don't suggest an operator based on complex heuristics, instead I suggest > a very simple and fast one (>10 times than magrittr in my tests) : > > `%.%` <- function (e1, e2) { > eval(substitute(e2), envir = list(. = e1), enclos = parent.frame()) > } > > iris %.% head(.) %.% dim(.) > #> [1] 6 5 > > The difference with magrittr is that the dots must all be explicit (which > sits with the choice of the name), and that special magrittr features such > as assignment in place and building functions with `. %>% head() %>% dim()` > are not supported. > > Edge cases are not surprising: > > ``` > x <- "a" > x %.% quote(.) > #> . > x %.% substitute(.) > #> [1] "a" > > f1 <- function(y) function() eval(quote(y)) > f2 <- x %.% f1(.) > f2() > #> [1] "a" > ``` > > Looking forward for your thoughts on this, > > Antoine > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]
Actually, base R already has a pipe fairly close to the one you describe: ->.; iris ->.; head(.) ->.; dim(.) # [1] 6 5 I've called it the Bizarro pipe ( http://www.win-vector.com/blog/2016/12/magrittrs-doppelganger/ <http://www.win-vector.com/blog/2016/12/magrittrs-doppelganger/> ), and for some reason we chickened out and didn't spend time on it in the dot pipe paper ( https://journal.r-project.org/archive/2018/RJ-2018-042/index.html <https://journal.r-project.org/archive/2018/RJ-2018-042/index.html> ). For documentation Bizarro pipe has the advantage that one can work out how it works from the application itself, with out reference to a defining function.> On Oct 5, 2019, at 7:34 AM, Ant F <antoine.fabri at gmail.com> wrote: > > Dear R-devel, > > The most popular piping operator sits in the package `magrittr` and is used > by a huge amount of users, and imported /reexported by more and more > packages too. > > Many workflows don't even make much sense without pipes nowadays, so the > examples in the doc will use pipes, as do the README, vignettes etc. I > believe base R could have a piping operator so packages can use a pipe in > their code or doc and stay dependency free. > > I don't suggest an operator based on complex heuristics, instead I suggest > a very simple and fast one (>10 times than magrittr in my tests) : > > `%.%` <- function (e1, e2) { > eval(substitute(e2), envir = list(. = e1), enclos = parent.frame()) > } > > iris %.% head(.) %.% dim(.) > #> [1] 6 5 > > The difference with magrittr is that the dots must all be explicit (which > sits with the choice of the name), and that special magrittr features such > as assignment in place and building functions with `. %>% head() %>% dim()` > are not supported. > > Edge cases are not surprising: > > ``` > x <- "a" > x %.% quote(.) > #> . > x %.% substitute(.) > #> [1] "a" > > f1 <- function(y) function() eval(quote(y)) > f2 <- x %.% f1(.) > f2() > #> [1] "a" > ``` > > Looking forward for your thoughts on this, > > Antoine > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel--------------- John Mount http://www.win-vector.com/ <http://www.win-vector.com/> Our book: Practical Data Science with R https://www.manning.com/books/practical-data-science-with-r-second-edition <http://www.manning.com/zumel/> [[alternative HTML version deleted]]
How is your argument different to, say, "Should dplyr or data.table be part of base R as they are the most popular data science packages and they are used by a large number of users?" Kind regards On Sat, Oct 5, 2019 at 4:34 PM Ant F <antoine.fabri at gmail.com> wrote:> Dear R-devel, > > The most popular piping operator sits in the package `magrittr` and is used > by a huge amount of users, and imported /reexported by more and more > packages too. > > Many workflows don't even make much sense without pipes nowadays, so the > examples in the doc will use pipes, as do the README, vignettes etc. I > believe base R could have a piping operator so packages can use a pipe in > their code or doc and stay dependency free. > > I don't suggest an operator based on complex heuristics, instead I suggest > a very simple and fast one (>10 times than magrittr in my tests) : > > `%.%` <- function (e1, e2) { > eval(substitute(e2), envir = list(. = e1), enclos = parent.frame()) > } > > iris %.% head(.) %.% dim(.) > #> [1] 6 5 > > The difference with magrittr is that the dots must all be explicit (which > sits with the choice of the name), and that special magrittr features such > as assignment in place and building functions with `. %>% head() %>% dim()` > are not supported. > > Edge cases are not surprising: > > ``` > x <- "a" > x %.% quote(.) > #> . > x %.% substitute(.) > #> [1] "a" > > f1 <- function(y) function() eval(quote(y)) > f2 <- x %.% f1(.) > f2() > #> [1] "a" > ``` > > Looking forward for your thoughts on this, > > Antoine > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]
I +1 this idea, without judging the implementation details. The pipe operator has proven vastly popular. Adding it would be relatively easy (I think). Having it as part of the core would be a strong guarantee of the future stability of this syntax. On Sat, 5 Oct 2019 at 15:34, Ant F <antoine.fabri at gmail.com> wrote:> Dear R-devel, > > The most popular piping operator sits in the package `magrittr` and is used > by a huge amount of users, and imported /reexported by more and more > packages too. > > Many workflows don't even make much sense without pipes nowadays, so the > examples in the doc will use pipes, as do the README, vignettes etc. I > believe base R could have a piping operator so packages can use a pipe in > their code or doc and stay dependency free. > > I don't suggest an operator based on complex heuristics, instead I suggest > a very simple and fast one (>10 times than magrittr in my tests) : > > `%.%` <- function (e1, e2) { > eval(substitute(e2), envir = list(. = e1), enclos = parent.frame()) > } > > iris %.% head(.) %.% dim(.) > #> [1] 6 5 > > The difference with magrittr is that the dots must all be explicit (which > sits with the choice of the name), and that special magrittr features such > as assignment in place and building functions with `. %>% head() %>% dim()` > are not supported. > > Edge cases are not surprising: > > ``` > x <- "a" > x %.% quote(.) > #> . > x %.% substitute(.) > #> [1] "a" > > f1 <- function(y) function() eval(quote(y)) > f2 <- x %.% f1(.) > f2() > #> [1] "a" > ``` > > Looking forward for your thoughts on this, > > Antoine > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >-- Sent from Gmail Mobile [[alternative HTML version deleted]]
Hi John, Thanks, but the Bizzaro pipe comes with many flaws though : * It's not a single operator * It has a different precedence * It cannot be used in a subcall * The variable assigned to must be on the right * It doesn't trigger indentation when going to the line * It creates/overwrite a `.` variable in the worksace. And it doesn't deal gracefully with some lazy evaluation edge cases such as : compose <- function(f, g) { function(x) g(f(x)) } plus1 <- function(x) x + 1 plus2 <- plus1 %.% compose(.,plus1) plus2(5) #> [1] 7 plus1 ->.; compose(.,plus1) -> .; . -> plus2 plus2(5) #> Error: C stack usage 15923776 is too close to the limit What I propose on the other hand can always substitute any existing proper pipe in their standard feature, as long as the dot is made explicit. Best regards, Antoine Le sam. 5 oct. 2019 ? 16:59, John Mount <jmount at win-vector.com> a ?crit :> Actually, base R already has a pipe fairly close to the one you describe: > ->.; > > iris ->.; head(.) ->.; dim(.) > # [1] 6 5 > > I've called it the Bizarro pipe ( > http://www.win-vector.com/blog/2016/12/magrittrs-doppelganger/ ), and for > some reason we chickened out and didn't spend time on it in the dot pipe > paper ( https://journal.r-project.org/archive/2018/RJ-2018-042/index.html > ). > > For documentation Bizarro pipe has the advantage that one can work out how > it works from the application itself, with out reference to a defining > function. > > On Oct 5, 2019, at 7:34 AM, Ant F <antoine.fabri at gmail.com> wrote: > > Dear R-devel, > > The most popular piping operator sits in the package `magrittr` and is used > by a huge amount of users, and imported /reexported by more and more > packages too. > > Many workflows don't even make much sense without pipes nowadays, so the > examples in the doc will use pipes, as do the README, vignettes etc. I > believe base R could have a piping operator so packages can use a pipe in > their code or doc and stay dependency free. > > I don't suggest an operator based on complex heuristics, instead I suggest > a very simple and fast one (>10 times than magrittr in my tests) : > > `%.%` <- function (e1, e2) { > eval(substitute(e2), envir = list(. = e1), enclos = parent.frame()) > } > > iris %.% head(.) %.% dim(.) > #> [1] 6 5 > > The difference with magrittr is that the dots must all be explicit (which > sits with the choice of the name), and that special magrittr features such > as assignment in place and building functions with `. %>% head() %>% dim()` > are not supported. > > Edge cases are not surprising: > > ``` > x <- "a" > x %.% quote(.) > #> . > x %.% substitute(.) > #> [1] "a" > > f1 <- function(y) function() eval(quote(y)) > f2 <- x %.% f1(.) > f2() > #> [1] "a" > ``` > > Looking forward for your thoughts on this, > > Antoine > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > > > --------------- > John Mount > http://www.win-vector.com/ > Our book: Practical Data Science with R > https://www.manning.com/books/practical-data-science-with-r-second-edition > <http://www.manning.com/zumel/> > > > > >[[alternative HTML version deleted]]
On Sat, 5 Oct 2019 at 17:15, Hugh Marera <hugh.marera at gmail.com> wrote:> > How is your argument different to, say, "Should dplyr or data.table be > part of base R as they are the most popular data science packages and they > are used by a large number of users?"Two packages with many features, dozens of functions and under heavy development to fix bugs, add new features and improve performance, vs. a single operator with a limited and well-defined functionality, and a reference implementation that hasn't changed in years (but certainly hackish in a way that probably could only be improved from R itself). Can't you really spot the difference? I?aki