5

How can I use the Map function with the pipe base |>?

The next x vector can be used inside the Map function

x <- c(1,5,1,2)
Map(function(n)n*2, x) |> unlist()
# [1]  2 10  2  4

This works, but when I try to use the pipe I get the next error:

x |> Map(function(n)n*2, ...= _)
#Error in (function (n)  : unused argument (... = dots[[1]][[1]])

So I make another anonymous function, but it is difficult to read

x |> (function(x) Map(function(n)n*2,x))() |> unlist()
#[1]  2 10  2  4

I would like to know why the Map can't take the place holder _.

Another solution

I change the order of the arguments of Map so It can be more legible

myMap <- \(...,f) Map(f, ...)
x |> myMap(f = function(n)n*2) |> unlist()
#[1]  2 10  2  4
Henrik
  • 65,555
  • 14
  • 143
  • 159
juarpasi
  • 88
  • 6
  • What is the reason to use `Map`? In this case there is no need for it as `x |> (\(n) n*2)()` or `x*2` will already work. – GKi May 24 '23 at 06:48
  • It was just to exemplify the problem. You're right, there's no need to use a `Map` as vectorization is more efficient. Actually, i was using a list in a pipe flow. Something like this `l |> Filter |> Map |> Reduce`. `Map` does not accept the place holder as `Filter` and `Reduce`, and I couldn't understand why – juarpasi May 24 '23 at 09:31
  • So do the Answers help to solve this? – GKi May 24 '23 at 09:33
  • Yes, thanks a lot, I will edit the question to add your contributions – juarpasi May 24 '23 at 09:39

2 Answers2

6

You can try to name the function so the first free position is used by the pipe.

x |> Map(f=function(n)n*2) |> unlist()
#[1]  2 10  2  4

But Map or mapply typical are used for multiple arguments and here either the position or the given name matters. The placeholder _ currently (R 4.3.0) needs named argument, also for functions which have only ... but here any free name could be used.

 1:3 |> mapply(`paste`, 1, .=_)
#[1] "1 1" "1 2" "1 3"

1:3 |> mapply(`paste`, .=_, 1)
#[1] "1 1" "2 1" "3 1"

1:3 |> mapply(`paste`, x=_, 1)
#[1] "1 1" "2 1" "3 1"

In case the function uses the names, the same names need to be used as an argument for Map or mapply.

1:3 |> Map(seq, 1, to=_)
#[[1]]
#[1] 1
#
#[[2]]
#[1] 1 2
#
#[[3]]
#[1] 1 2 3

1:3 |> Map(seq, 1, from=_)
#[[1]]
#[1] 1
#
#[[2]]
#[1] 2 1
#
#[[3]]
#[1] 3 2 1
GKi
  • 37,245
  • 2
  • 26
  • 48
3
x |> Map(function(n) n * 2, n = _) |> unlist()

The reason is that Map is basically mapply

mapply calls FUN for the values of ... (re-cycled to the length of the longest, unless any have length zero where recycling to zero length will return list()), followed by the arguments given in MoreArgs. The arguments in the call will be named if ... or MoreArgs are named.

So, your function has a named argument n, therefore, you can pipe into that argument.

Hieu Nguyen
  • 492
  • 3
  • 8