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

Add option to use try from in extendr macro #222

Merged
merged 3 commits into from
Jul 15, 2021

Conversation

andy-thomason
Copy link
Contributor

This PR adds an option:

#[extendr(use_try_from = true)]
fn test_i32(val: i32) -> i32 {
    val
}

This is a prelude to supporting the try_from error handling formally.

It should have no effect on the main branch and so, we may merge this to enable others to contribute
to writing conversions.

We may need the failing conversion to give a useful error message by using to_string() on the returned
error.

We should then write integration tests to check these messages in R.

Note that Option gives None if T is a NA value, not NULL.

There is another wrapper Nullable which handles NULLs.

Copy link
Member

@clauswilke clauswilke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks fine to me. I had a few minor comments.

}

#[test]
fn happy_path() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use a more descriptive function name? E.g. tests_without_error()?

@@ -1,6 +1,6 @@
//! R object handling.
//!
//! See. https://cran.r-project.org/doc/manuals/R-exts.html
//! See. <https://cran.r-project.org/doc/manuals/R-exts.html>
//!
//! Fundamental principals:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean "principles"?

}

// Win32 does not support catch_unwind.
#[cfg(not(target_arch = "x86"))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to make this test Windows specific? Or is x86 specific to Windows?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the problem (catch_unwind not supported) is x86 specific, rather than windows,
but Windows (XP) is currently our only x86 target.

Getting the tests to run green is a priority here, we could refine later.

// Win32 does not support catch_unwind.
#[cfg(not(target_arch = "x86"))]
#[test]
fn sad_path() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above. E.g., tests_with_errors().

-1
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a test_option_bool as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll merge this into main. Feel free to add more tests.

// NA input.
assert_eq!(new_owned(wrap__test_option_f64(r!(NA_INTEGER).get())), r!(-1.0));
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if adding test_option_bool above: a series for logical

@brendanrbrown
Copy link
Contributor

brendanrbrown commented Jul 15, 2021

looks nice -- i've commented on one test that snuck away this time, but adding it could be (edit perhaps was intended to be) work for others as you mentioned in #219.

assert_eq!(new_owned(wrap__test_i32(r!(1).get())), r!(1));

// i32 takes any numeric.
assert_eq!(new_owned(wrap__test_i32(r!(1.0).get())), r!(1));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure what 'takes any numeric' means here. What will happen if we pass 1.5?
What would be the behavior?
If the value is somehow truncated/converted to integer space, this may be an issue, and extremely hard to debug.

Same applies to Option<i32>

If this is OK, may I then suggest to add another option, like #[extendr(use_strict_types = true)] or #[extendr(vctrs_compat = true)] to enable strict type checks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you feel like doing so, we should replace the "as" in impl_try_from_scalar! with TryFrom.
This would also range-check small numbers.

I'm going to close this ASAP so that more PRs can follow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now have a template for adding other options, so suggestions like this are welcome.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wanted to point out that I think strict type checks should be the default, not optional. If somebody writes i32 as their input type we shouldn't silently round from 1.5 to 1, we should throw a runtime error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fully support this. My preferred solution would be something similar to {vctrs} behavior, which should at least be available as an option.



// Matching integer.
assert_eq!(new_owned(wrap__test_option_i16(r!(1).get())), r!(1));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without having a deep understanding of what #[extendr(use_try_from = true)] produces, I would suggest adding tests for int values outside of i16 value space.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the comment above about replacing the "as".

Copy link
Member

@Ilia-Kosenkov Ilia-Kosenkov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the new approach using options in #[extendr], this should speed up feature development.

@andy-thomason andy-thomason merged commit 2103979 into master Jul 15, 2021
@andy-thomason andy-thomason deleted the add-option-to-use-try-from-in-extendr-macro branch July 15, 2021 12:02
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

Successfully merging this pull request may close these issues.

None yet

4 participants