-
Notifications
You must be signed in to change notification settings - Fork 128
From<??> for RObject and PartialEq<??> for RObject where ?? is a slice of vector of strings (&str or String)
#118
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
Conversation
|
By convention, the From trait is used to implement "consuming value-to-value" conversions. See for example: https://doc.rust-lang.org/std/convert/index.html For that reason, I think the original implementation is still preferred here. |
| Ok(actual) | ||
| } | ||
|
|
||
| pub unsafe fn r_strings_eq(object: SEXP, expected: &Vec<&str>) -> bool { |
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.
I wonder if this could be implemented as a trait / method on the RObject class, so one could write:
let object = RObject::new();
object.equals(something);
and then we'd have separate implementations for the various kinds of objects we care about. This would keep the API a little bit cleaner, I think?
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 that seems like a reasonable approach, we could add something here:
and then have various implementations of that trait for different RHS objects.
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.
I'd say we can sit on this for now, perhaps we'll want to have dedicated rust classes instead of a catch all RObject i.e. the same way we have cpp11::strings They could have dedicated traits
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.
I went another direction so that we can assert_eq!() an RObject with strings, with various "strings"
fn test_RObject_from_Vec_str() { r_test! {
let expected = ["Apple", "Orange", "한"];
// RObject from Vec<&str>
let r_strings = RObject::from(expected.to_vec());
assert_eq!(r_strings, expected); // [&str]
assert_eq!(r_strings, expected[..]); // [&str; const N]
assert_eq!(r_strings, expected.to_vec()); // Vec<&str>
assert_eq!(expected , r_strings); // [&str]
assert_eq!(expected[..] , r_strings); // [&str; const N]
assert_eq!(expected.to_vec(), r_strings); // Vec<&str>
}}
Thanks. I'll rewind that part of the PR then, it makes sense. My thinking was "this is going to create new strings anyway, so we might as well keep the old value". |
| let vector = Rf_protect(Rf_allocVector(STRSXP, n)); | ||
| for i in 0..n { | ||
| let string = value[i as usize]; | ||
| let c_string = CString::new(string).unwrap(); |
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.
I believe you want CStr rather than CString here, as the memory for the string is "owned" by the Rust vector.
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.
Using something different with:
impl ToCharSxp for &str {
fn to_charsxp(&self) -> SEXP {
unsafe {
Rf_mkCharLenCE(self.as_ptr() as *mut c_char, self.len() as i32, cetype_t_CE_UTF8)
}
}
}
impl ToCharSxp for String {
fn to_charsxp(&self) -> SEXP {
(&self[..]).to_charsxp()
}
}The problem usually is that self.as_ptr() is not null terminated, but Rf_mkCharLenCE() does not care about that.
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.
The problem usually is that self.as_ptr() is not null terminated, but Rf_mkCharLenCE() does not care about that.
Interesting -- I guess R is null terminating the string for us? I was curious whether that was true and it looks like it happens here:
Presumedly R is also allocating and zeroing the memory somewhere as well, but I got dizzy after scrolling further down...
…m<Vec<S>> for RObject where S : ToCharSxp
…Eq trait that is only implemented for &str and String
From<Vec<String>> for RObject -> From<&Vec<String>>From<Vec<&str | String>> and PartialEq<??> for RObject where ?? is a slice of vector of strings (&str or String)
From<Vec<&str | String>> and PartialEq<??> for RObject where ?? is a slice of vector of strings (&str or String) From<??> for RObject and PartialEq<??> for RObject where ?? is a slice of vector of strings (&str or String)
kevinushey
left a comment
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.
LGTM; nice work!
For now, let's leave other extensions to harp until we know we need them; e.g. I'm sure we'll want some subset of methods when we think about how to summarize or describe an object in short form but let's implement them as we find they're required -- we don't need a "complete" API at this point, we can build it as we go.
| let vector = Rf_protect(Rf_allocVector(STRSXP, n)); | ||
| for i in 0..n { | ||
| let string = value[i as usize]; | ||
| let c_string = CString::new(string).unwrap(); |
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.
The problem usually is that self.as_ptr() is not null terminated, but Rf_mkCharLenCE() does not care about that.
Interesting -- I guess R is null terminating the string for us? I was curious whether that was true and it looks like it happens here:
Presumedly R is also allocating and zeroing the memory somewhere as well, but I got dizzy after scrolling further down...
Definitely. I'm very conscious about the risk of spending too much time crafting the perfect seamless I'll come back to it as needs materialize higher up. |
… >= 3.8 Merge pull request #118 from posit-dev/limit-registered-runtimes limit registered runtimes to >= 3.8 -------------------- Commit message for posit-dev/positron-python@30bb1a5: ignore pre-existing file with pyright issues -------------------- Commit message for posit-dev/positron-python@cb6fca8: limit registered runtimes to >= 3.8 Addresses #654. Authored-by: Wasim Lorgat <mwlorgat@gmail.com> Signed-off-by: Wasim Lorgat <mwlorgat@gmail.com>
… >= 3.8 Merge pull request #118 from posit-dev/limit-registered-runtimes limit registered runtimes to >= 3.8 -------------------- Commit message for posit-dev/positron-python@30bb1a5: ignore pre-existing file with pyright issues -------------------- Commit message for posit-dev/positron-python@cb6fca8: limit registered runtimes to >= 3.8 Addresses #654. Authored-by: Wasim Lorgat <mwlorgat@gmail.com> Signed-off-by: Wasim Lorgat <mwlorgat@gmail.com>
Now only borrows, i.e.
impl From<&Vec<String>> for RObjectand correctly constructs the CHARSXP (this is what dragged me here in the first place).Or did we really mean for the passed
Vecto be dropped ?