iuke-tier@ey m@iii@g oii uiow@@edu
2021-Jan-12 19:23 UTC
[Rd] [External] brief update on the pipe operator in R-devel
After some discussions we've settled on a syntax of the form mtcars |> subset(cyl == 4) |> d => lm(mpg ~ disp, data = d) to handle cases where the pipe lhs needs to be passed to an argument other than the first of the function called on the rhs. This seems a to be a reasonable balance between making these non-standard cases easy to see but still easy to write. This is now committed to R-devel. Best, luke On Tue, 22 Dec 2020, luke-tierney at uiowa.edu wrote:> It turns out that allowing a bare function expression on the > right-hand side (RHS) of a pipe creates opportunities for confusion > and mistakes that are too risky. So we will be dropping support for > this from the pipe operator. > > The case of a RHS call that wants to receive the LHS result in an > argument other than the first can be handled with just implicit first > argument passing along the lines of > > mtcars |> subset(cyl == 4) |> (\(d) lm(mpg ~ disp, data = d))() > > It was hoped that allowing a bare function expression would make this > more convenient, but it has issues as outlined below. We are exploring > some alternatives, and will hopefully settle on one soon after the > holidays. > > The basic problem, pointed out in a comment on Twitter, is that in > expressions of the form > > 1 |> \(x) x + 1 -> y > 1 |> \(x) x + 1 |> \(y) x + y > > everything after the \(x) is parsed as part of the body of the > function. So these are parsed along the lines of > > 1 |> \(x) { x + 1 -> y } > 1 |> \(x) { x + 1 |> \(y) x + y } > > In the first case the result is assigned to a (useless) local > variable. Someone writing this is more likely to have intended to > assign the result to a global variable, as this would: > > (1 |> \(x) x + 1) -> y > > In the second case the 'x' in 'x + y' refers to the local variable 'x' > in the first RHS function. Someone writing this is more likely to have > meant > > (1 |> \(x) x + 1) |> \(y) x + y > > with 'x' in 'x + y' now referring to a global variable: > > > x <- 2 > > 1 |> \(x) x + 1 |> \(y) x + y > [1] 3 > > (1 |> \(x) x + 1) |> \(y) x + y > [1] 4 > > These issues arise with any approach in R that allows a bare function > expression on the RHS of a pipe operation. It also arises in other > languages with pipe operators. For example, here is the last example > in Julia: > > julia> x = 2 > 2 > julia> 1 |> x -> x + 1 |> y -> x + y > 3 > julia> ( 1 |> x -> x + 1 ) |> y -> x + y > 4 > > Even though proper use of parentheses can work around these issues, > the likelihood of making mistakes that are hard to track down is too > high. So we will disallow the use of bare function expressions on the > right hand side of a pipe. > > Best, > > luke > >-- Luke Tierney Ralph E. Wareham Professor of Mathematical Sciences University of Iowa Phone: 319-335-3386 Department of Statistics and Fax: 319-335-3017 Actuarial Science 241 Schaeffer Hall email: luke-tierney at uiowa.edu Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
IƱaki Ucar
2021-Jan-12 19:38 UTC
[Rd] [External] brief update on the pipe operator in R-devel
On Tue, 12 Jan 2021 at 20:23, <luke-tierney at uiowa.edu> wrote:> > After some discussions we've settled on a syntax of the form > > mtcars |> subset(cyl == 4) |> d => lm(mpg ~ disp, data = d) > > to handle cases where the pipe lhs needs to be passed to an argument > other than the first of the function called on the rhs. This seems a > to be a reasonable balance between making these non-standard cases > easy to see but still easy to write. This is now committed to R-devel.Interesting. Is the use of "d =>" restricted to pipelines? In other words, I think that it shouldn't be equivalent to "function(d)", i.e., that this: x <- d => lm(mpg ~ disp, data = d) shouldn't work. -- I?aki ?car