-
Notifications
You must be signed in to change notification settings - Fork 10
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
purrr map2 can't find a function while nested inside another function #204
Comments
This would be the consequence of purrr's auto-crating behaviour. See 'Crating a function' under It's designed in part to guard against shipping large objects in a function's enclosing environment when they're not even needed by it (can easily happen when dealing with nested functions). You would need to crate your anonymous function in the following way: some_fun1 <- function(x, y) {
sum_fun1 <- function(a, b) {
a + b
}
get_sum1 <-
purrr::map2(
x,
y,
carrier::crate(
\(x1, x2) {
sum_fun1(x1, x2)
},
sum_fun1 = sum_fun1
),
.parallel = TRUE
)
return(get_sum1)
} Purrr uses the carrier package, but it's a similar concept to using the |
Is there any way to use ...? library(mirai)
x <- c(1, 2, 3)
y <- c(10, 20, 30)
some_fun1 <- function(x, y, ...) {
sum_fun1 <- function(a, b, ...) {
a + b
}
get_sum1 <-
purrr::map2(
x,
y,
carrier::crate(
\(x1, x2) {
sum_fun1(x1, x2, ...)
},
sum_fun1 = sum_fun1
),
.parallel = TRUE
)
return(get_sum1)
}
daemons(3)
#> [1] 3
some_fun1(x, y)
#> Error in `purrr::map2()`:
#> ℹ In index: 1.
#> Caused by error:
#> ! '...' used in an incorrect context
daemons(0)
#> [1] 0 Created on 2025-02-10 with reprex v2.1.1 |
I think this gets me pretty close to where I want to be. library(mirai)
daemons(3)
#> [1] 3
x <- c(1, 2, 3)
y <- c(10, 20, 30)
some_fun1 <- function(x, y, ...) {
sum_fun1 <- function(a, b, ...) {
args <- list(a = a, b = b)
dots <- list(...)
if (length(dots) != 0) {
args <- append(args, dots)
}
args
}
dots <- list(...)
get_sum1 <-
purrr::map2(
x,
y,
carrier::crate(
\(x1, x2) {
sum_fun1(x1, x2, !!!dots)
},
sum_fun1 = sum_fun1
),
.parallel = TRUE
)
return(get_sum1)
}
some_fun1(x, y)
#> [[1]]
#> [[1]]$a
#> [1] 1
#>
#> [[1]]$b
#> [1] 10
#>
#>
#> [[2]]
#> [[2]]$a
#> [1] 2
#>
#> [[2]]$b
#> [1] 20
#>
#>
#> [[3]]
#> [[3]]$a
#> [1] 3
#>
#> [[3]]$b
#> [1] 30
some_fun1(x, y, z = 10)
#> [[1]]
#> [[1]]$a
#> [1] 1
#>
#> [[1]]$b
#> [1] 10
#>
#> [[1]]$z
#> [1] 10
#>
#>
#> [[2]]
#> [[2]]$a
#> [1] 2
#>
#> [[2]]$b
#> [1] 20
#>
#> [[2]]$z
#> [1] 10
#>
#>
#> [[3]]
#> [[3]]$a
#> [1] 3
#>
#> [[3]]$b
#> [1] 30
#>
#> [[3]]$z
#> [1] 10
some_fun1(x, y, z = 10, m = 20)
#> [[1]]
#> [[1]]$a
#> [1] 1
#>
#> [[1]]$b
#> [1] 10
#>
#> [[1]]$z
#> [1] 10
#>
#> [[1]]$m
#> [1] 20
#>
#>
#> [[2]]
#> [[2]]$a
#> [1] 2
#>
#> [[2]]$b
#> [1] 20
#>
#> [[2]]$z
#> [1] 10
#>
#> [[2]]$m
#> [1] 20
#>
#>
#> [[3]]
#> [[3]]$a
#> [1] 3
#>
#> [[3]]$b
#> [1] 30
#>
#> [[3]]$z
#> [1] 10
#>
#> [[3]]$m
#> [1] 20
daemons(0)
#> [1] 0 Created on 2025-02-12 with reprex v2.1.1 |
Got it. There are two solutions: Bundle all the inputs that aren't being iterated into a list some_fun1 <- function(x, y, n = NULL, ...) {
sum_fun1 <- function(a, b, n, ...) {
args <- list(a = a, b = b, n = n)
dots <- list(...)
if (length(dots) != 0) {
args <- append(args, dots)
}
args
}
args <- list(n = n)
dots <- list(...)
if (length(dots) != 0) {
args <- append(args, dots)
}
get_sum1 <-
purrr::map2(
x,
y,
carrier::crate(
\(x1, x2) {
sum_fun1(x1, x2, !!!args)
},
sum_fun1 = sum_fun1
),
.parallel = TRUE
)
return(get_sum1)
}
Or unquote the inputs not being iterated individually some_fun1 <- function(x, y, n = NULL, ...) {
sum_fun1 <- function(a, b, n, ...) {
args <- list(a = a, b = b, n = n)
dots <- list(...)
if (length(dots) != 0) {
args <- append(args, dots)
}
args
}
dots <- list(...)
get_sum1 <-
purrr::map2(
x,
y,
carrier::crate(
\(x1, x2) {
sum_fun1(x1, x2, n = !!n, !!!dots)
},
sum_fun1 = sum_fun1
),
.parallel = TRUE
)
return(get_sum1)
}
some_fun1(x, y)
some_fun1(x, y, n = 5)
some_fun1(x, y, n = 5, z = 10)
some_fun1(x, y, n = 5, z = 10, m = 20) |
Even only doing 2 iterations with the function I using this for, I get a 41%(?) speed-up 👍. ... with 4 iterations, that's a 67% speed-up I think 👍👍 |
Created on 2025-02-10 with reprex v2.1.1
Session Info
The text was updated successfully, but these errors were encountered: