3

In R 4.1 a native pipe operator was introduced that is "more streamlined" than previous implementations. See this post about it.

This is a question inspired by the thread "What are the differences between R's new native pipe |> and the magrittr pipe %>%?".

I will leave aside the magritter pipe where a %>% b(...) is most commonly used to denote {. <- a; b(., ...)} (with dot side effects hidden) because it is clearly different.

I found this thread helpful in understanding the |> does "just" functional composition with no discernible overhead.

The old native pipe ->.; is lengthy but works perfectly for functional composition.
The old native pipe ->.; is composed of:

  • -> assignment,
  • . variable,
  • ; statement end

Both seem practically the same for usual purposes.

1:3 |> sum()
#> [1] 6
1:3 ->.; sum(.)
#> [1] 6

The old native pipe uses dot placeholder.

mtcars ->.;
 lm(mpg ~ disp, data = .)
#> 
#> Call:
#> lm(formula = mpg ~ disp, data = .)
#> 
#> Coefficients:
#> (Intercept)         disp  
#>    29.59985     -0.04122

The new native pipe doesn’t have a placeholder.

mtcars |> 
  lm(mpg ~ disp, data = .)
#> Error in is.data.frame(data): object '.' not found

mtcars |> 
  lm(mpg ~ disp)
#> Error in as.data.frame.default(data): cannot coerce class '"formula"' to a data.frame

This means you have to do function declaration gymnastics to make it work when you don't want to pipe into the first unnamed argument.

mtcars |> 
  (function(x) lm(mpg ~ disp, data = x))()
#> 
#> Call:
#> lm(formula = mpg ~ disp, data = x)
#> 
#> Coefficients:
#> (Intercept)         disp  
#>    29.59985     -0.04122

mtcars |> 
  (\(x) lm(mpg ~ disp, data = x))()         # alternative new function-creation syntax 
#> 
#> Call:
#> lm(formula = mpg ~ disp, data = x)
#> 
#> Coefficients:
#> (Intercept)         disp  
#>    29.59985     -0.04122

I really want to understand the new pipe and its utility.

  • Are there any useful patterns you found that are facilitated by |>?
  • Does the development of => operator that is "available but not active" change the prospects for |>?
  • When needing only functional composition why don't we use the old pipe ->.;? Why is it so underutilized, while the new |> gets all the love?

I love R and I would like to love its newer developments. This is why I need to understand. Any insightful answers are welcome.

Claudiu Papasteri
  • 2,469
  • 1
  • 17
  • 30
  • 3
    `->.;` is not a pipe. You are just assigning a vector into an object named `.` and then using `;` to break R into a new line to run something else. – Phil Feb 17 '22 at 15:33
  • 1
    I don't consider myself knowledgeable enough to argue if that isn't just semantics. The `wrapr` package has a dot-pipe `%.>%` that does exactly `{ . <- a; b };`. Is that also *not a pipe* (sorry for the Magritte pun, but pipes do invite it)? Again, I am just trying to understand and I think you should post your comment as an answer so it can generate focused discussion on what a pipe is or isn't. – Claudiu Papasteri Feb 17 '22 at 15:47
  • 1
    If the code at some level is assigning data into an object, than IMO it is not a pipe, it just masquerades as such. After you run `1:3 ->.; sum(.)`, just run `.` and you'll get the vector `1 2 3`. When using either `|>` or `%>%` there is no such assignment occurring into the environment. – Phil Feb 17 '22 at 15:56
  • 2
    The `|>` operator re-writes the expression at the R parser level to basically remove itself and rewrite your expression. For example `quote(x |> sin())` shows that the `|>` disappears after the parse processes the expression. It's a more optimized procedure and has no side effects. The `->.;` makes using `.` as a variable impossible. There's no such variable clobbering with `|>` – MrFlick Feb 17 '22 at 15:57
  • Have a look at: [Does the Bizarro pipe ->.; have disadvantages making it not recommended for use?](https://stackoverflow.com/q/67868289/10488504) – GKi May 02 '22 at 13:13

0 Answers0