Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ellipsis in as_mapper #710

Closed
TimTeaFan opened this issue Oct 5, 2019 · 3 comments
Closed

Ellipsis in as_mapper #710

TimTeaFan opened this issue Oct 5, 2019 · 3 comments

Comments

@TimTeaFan
Copy link

TimTeaFan commented Oct 5, 2019

We encountered an issue when using the ellipsis argument in as_mapper.

It seems that when the ellipsis is included in the mapper function, as_mapper matches the first argument not only to .x but also automatically to the ellipsis ....

Below is a short example of what is happening when using the ellipsis inside a mapper function.

paster <- purrr::as_mapper(~ paste0(.x, ...))
paster(1)
> [1] "11"
paster(2)
> [1] "22"
paster(1,1)
> [1] "111"

The question now is:

  1. is there another way we are supposed to use ellipsis in mapper functions
  2. is there a reason for this behavior and should we therefor refrain from using the ellipsis in mapper function or
  3. is this a bug.

Update
The above behavior does not appear, when specifying the .x argument explicitly in the paster function. It seems like ... is already used within as_mapper which leads to conflicts. I then wonder why not specifying the argument in paster will map the value to both .x and ....

paster(.x = 1)
>[1] "1"
paster(.x = 1, 1)
> [1] "11"

And while in the above example the specification of .x as argument is still possible, the argument matching inside as_mapper becomes an actual issue when used inside a function (which is generally the case when using one of the map-functions together with the lambda notion for .f ~).

map_paster <- function(x, ...) {
     map(x, ~ paste0(.x, ...))
}
map_paster(x = 1:3)
>[[1]]
>[1] "11"
>
>[[2]]
>[1] "22"
>
>[[3]]
>[1] "33"
@TimTeaFan
Copy link
Author

TimTeaFan commented Oct 7, 2019

I think I found the (more general) answer to my question.

Rewriting the map_paster function from above as follows as ...

map_paster <- function(z, ...) {
  dots <- match.call(expand.dots = FALSE)$...
  map(z, ~ paste0(.x, dots))
}

... suggests that we are supposed to use ellipsis in mapper functions (and all other nested functions in general) differently then in non-nested functions.

However, it would still be interesting to know why the argument mapping goes wrong, when the ellipsis is passed as is into the nested-function/mapper function.

@moodymudskipper
Copy link
Contributor

moodymudskipper commented Jan 13, 2020

Look at the definition :

paster <- purrr::as_mapper(~ paste0(.x, ...))
paster
#> <lambda>
#> function (..., .x = ..1, .y = ..2, . = ..1) 
#> paste0(.x, ...)
#> attr(,"class")
#> [1] "rlang_lambda_function" "function"

.x is ..1 by default, i.e. the first element of the dots (if you feed it explicitly as you do in your example it's not ..1 anymore, and is not fed to the dots either since it's named).

I'm not sure if as_mapper() is appropriate for your use case as it seems you'd like a function with the formals .x and ... in that order, and as_mapper() won't give you that.

We could reproduce the functionality though :

paster <- purrr::as_mapper(~ rlang::exec(paste0,.x, !!!list(...)[-1]))
paster(1)
#> [1] "1"
paster(1,2,3)
#> [1] "123"

But it's probably not worth the trouble when you could use a regular function(){} definition in this case.

@TimTeaFan
Copy link
Author

Thanks for digging into this. I stumbled upon the issue on SO (see link in original post above) where as_mapper is used inside map and the argument order is given by the original function which is first transformed with as_mapper.

When the function inside map takes additional arguments by ... then one can either

  1. use an anonymous function instead (see the SO post)
  2. use dots <- match.call(expand.dots = FALSE)$... or
  3. use your suggested approach to get around the double mapping of '.x'

I think this issue is not really an 'issue' and can be closed.

@TimTeaFan TimTeaFan reopened this Jan 17, 2020
@lionel- lionel- closed this as completed Jan 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants