What are the differences between R’s new native pipe `|>` and the magrittr pipe `%>%`?

In R 4.1, there was no placeholder syntax for the native pipe. Thus, there was no equivalent of the . placeholder of magrittr and thus the following was impossible with |>.

c("dogs", "cats", "rats") %>% grepl("at", .)
#[1] FALSE  TRUE  TRUE

As of R 4.2, the native pipe can use _ as a placeholder but only with named arguments.

c("dogs", "cats", "rats") |> grepl("at", x = _)
#[1] FALSE  TRUE  TRUE

The . and magrittr is still more flexible as . can be repeated and appear in expressions.

c("dogs", "cats", "rats") %>% 
  paste(., ., toupper(.)) 
#[1] "dogs dogs DOGS" "cats cats CATS" "rats rats RATS"

c("dogs", "cats", "rats") |>
  paste(x = "no", y = _) 
# Error in paste(x = "_", y = "_") : pipe placeholder may only appear once

It is also not clear how to use |> with a function that takes in unnamed variadic arguments (i.e., ...). In this paste() example, we can make up x and y arguments to trick the placeholder in the correct place, but that feels hacky.

c("dogs", "cats", "rats") |>
  paste(x = "no", y = _) 
#[1] "no dogs" "no cats" "no rats"

Here are additional ways to work around the place holder limitations-

  1. Write a separate function
find_at = function(x) grepl("at", x)
c("dogs", "cats", "rats") |> find_at()
#[1] FALSE  TRUE  TRUE
  1. Use an anonymous function

    a) Use the “old” syntax

    c("dogs", "cats", "rats") |> {function(x) grepl("at", x)}()
    

    b) Use the new anonymous function syntax

    c("dogs", "cats", "rats") |> {\(x) grepl("at", x)}()
    
  2. Specify the first parameter by name. This relies on the fact that the native pipe pipes into the first unnamed parameter, so if you provide a name for the first parameter it “overflows” into the second (and so on if you specify more than one parameter by name)

c("dogs", "cats", "rats") |> grepl(pattern="at")
#> [1] FALSE  TRUE  TRUE

Leave a Comment