From iuke-tier@ey m@iii@g oii uiow@@edu  Tue Jan 12 20:23:06 2021
From: iuke-tier@ey m@iii@g oii uiow@@edu (iuke-tier@ey m@iii@g oii uiow@@edu)
Date: Tue, 12 Jan 2021 13:23:06 -0600 (CST)
Subject: [Rd] [External]  brief update on the pipe operator in R-devel
In-Reply-To: <alpine.DEB.2.21.2012221624270.3391@luke-Latitude-7480>
References: <alpine.DEB.2.21.2012221624270.3391@luke-Latitude-7480>
Message-ID: <alpine.DEB.2.21.2101121317310.3211@luke-Latitude-7480>

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



[Rd] [External] brief update on the pipe operator in R-devel
iuke-tier@ey m@iii@g oii uiow@@edu