-
Notifications
You must be signed in to change notification settings - Fork 272
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
Add iteration index to errors #945
Conversation
@@ -3,7 +3,13 @@ | |||
Code | |||
map_depth(x1, 6, length) | |||
Condition | |||
Error in `map_depth()`: | |||
Error in `.fmap()`: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is verbose, but it's technically correct and possibly helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably fine for this particular function. I'm expecting this sort of errors to be internal errors rather than user errors.
Noting that when all of the map friends are converted over to use this, on the C side we shouldn't create and overwrite Lines 39 to 42 in 426acdd
Since it already exists in the function environment through |
Conflicts: R/map.R tests/testthat/_snaps/map2.md tests/testthat/_snaps/modify.md
Can we improve on these two cases? > map(-1:1, stop)
Error in `map()`:
! Computation failed in index 1
Caused by error in `withCallingHandlers()`:
! -1
Run `rlang::last_trace()` to see where the error occurred. fn <- function(x) {
if (x == 2) {
rlang::abort("oh no")
}
x
}
map(-1:3, fn)
Error in `map()`:
! Computation failed in index 4
Caused by error in `.f()`:
! oh no
Run `rlang::last_trace()` to see where the error occurred. |
And make sure it's an integer
@DavisVaughan I think our conclusion was that we can't easily improve on that, right? library(purrr)
# call. is TRUE by default
map(-1:1, stop)
#> Error in `map()`:
#> ! Computation failed in index 1
#> Caused by error in `withCallingHandlers()`:
#> ! -1
map("a", rlang::abort)
#> Error in `map()`:
#> ! Computation failed in index 1
#> Caused by error in `map()`:
#> ! a
# have lost original name of function
fn <- function(x) {
if (x == 2) {
rlang::abort("oh no")
}
x
}
map(-1:3, fn)
#> Error in `map()`:
#> ! Computation failed in index 4
#> Caused by error in `.f()` at purrr/R/map.R:117:2:
#> ! oh no
map(-1:3, \(x) fn(x))
#> Error in `map()`:
#> ! Computation failed in index 4
#> Caused by error in `fn()`:
#> ! oh no Created on 2022-09-21 with reprex v2.0.2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! But I think it'd make sense to think about call
arguments to take ownership of map errors, as argued inline.
@@ -3,7 +3,13 @@ | |||
Code | |||
map_depth(x1, 6, length) | |||
Condition | |||
Error in `map_depth()`: | |||
Error in `.fmap()`: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably fine for this particular function. I'm expecting this sort of errors to be internal errors rather than user errors.
Extracting repeated code into map_, map2_, and pmap_
#Conflicts: # NEWS.md
i = i, | ||
error_call = .error_call, | ||
.Call(map_impl, environment(), .type, .progress, .error_call) | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is still pretty unfortunate that we get parent call information that mentions map_()
library(vctrs)
library(purrr)
map(1:5, vec_check_list)
#> Error in `map()`:
#> ! In index 1.
#> Caused by error in `map_()` at purrr/R/map.R:115:2:
#> ! `.x[[i]]` must be a list, not an integer.
It seems rare that the parent call is actually useful. I had mentioned that we might consider setting cnd$call <- NULL
or hardcoding it to .f
. Is that still an option? I feel like it would generally be less confusing because we'd have less chance of displaying confusing calls.
So it would look like:
> map(1:5, vec_check_list)
Error in `map()`:
! In index 1.
Caused by error:
! `.x[[i]]` must be a list, not an integer.
Run `rlang::last_trace()` to see where the error occurred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I strip the call from the error, I definitely lose useful information in the tests. So I think in most cases it is helpful, although it doesn't work so well with error checking functions. And you can already fix that if needed:
library(purrr)
my_f <- function() {
map(1:5, \(x) vctrs::vec_check_list(x, call = NULL))
}
my_f()
#> Error in `map()`:
#> ! Computation failed in index 1
#> Caused by error:
#> ! `x` must be a list, not an integer.
Created on 2022-09-23 with reprex v2.0.2
const char* l_name = CHAR(Rf_asChar(l_name_)); | ||
SEXP l = Rf_install(l_name); | ||
SEXP pmap_impl(SEXP env, SEXP type_, SEXP progress, SEXP error_call) { | ||
SEXP l = Rf_install(".l"); | ||
SEXP l_val = PROTECT(Rf_eval(l, env)); | ||
SEXPTYPE type = Rf_str2type(CHAR(Rf_asChar(type_))); | ||
|
||
if (!Rf_isVectorList(l_val)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!Rf_isVectorList(l_val)) { | |
if (TYPEOF(l_val) != VECSXP) { |
Rf_isVectorList()
allows EXPRSXP
for some reason and I feel like we don't want that. Does that feel right @lionel- ? https://github.com/wch/r-source/blob/79298c499218846d14500255efd622b5021c10ec/src/include/Rinlinedfuns.h#L851
Starting with purrr v1.0.0 the iteration when an error occurs is shown (tidyverse/purrr#945). This was causing this test to fail unnecessarily (it really shouldn't have been based on a snapshot).
Fixes #929
So far, just a quick proof of concept
To do:
map2
andpmap
functionscheck_vector()
/r_abort()
or move that check into R