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

Better list macro #303

Merged
merged 10 commits into from
Nov 23, 2021
Merged

Better list macro #303

merged 10 commits into from
Nov 23, 2021

Conversation

andy-thomason
Copy link
Contributor

This PR makes a procedural version of the list! macro which now returns the List type.

There are also a few structural changes to List.

As Robj is now a wrapper for SEXP we can express lists as an array of Robj types.

I have also added a more efficient method to create named lists.

Comment on lines 77 to 79
let mut list = List::from_values(values);
list.set_names(names).unwrap();
list
Copy link
Member

Choose a reason for hiding this comment

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

So what happens if names length does not equal to that of values? panic?

Copy link
Member

Choose a reason for hiding this comment

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

Good catch. I think this is a problem. Does the list! macro have the same problem?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The List macro should be guaranteed to make them the same length.

We probably should at least check the lengths in this function.

set_names is a bit dangerous as R may have some rules that it enforces.

I'm hoping that we will use the list! macro more than from_values_and_names in the future.

Copy link
Member

Choose a reason for hiding this comment

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

The question is, in this particular function, what happens if we provide 5 values and 2 names? There is no simple logic for generating 5 names from 2 strings, and I think it is important to understand.

let names: Vec<proc_macro2::TokenStream> =
nv.iter().map(|(n, _v)| quote!( #n )).collect();
TokenStream::from(quote!(
extendr_api::List::from_names_and_values(&[# ( #names ),*], &[# ( #values ),*]).unwrap()
Copy link
Member

Choose a reason for hiding this comment

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

It seems the advantage of the list macro is convenience, but at the cost of a panic if the input has the wrong format. I suggest you write this somewhere in the documentation.

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 should probably return an error.

This means we must use list!(...)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

At the moment, the only way it will unwrap and error is if it is not a List (always false) or the lengths do not match (always false).

So we should probably ignore this.

@@ -21,3 +21,20 @@ impl syn::parse::Parse for Pairs {
Ok(res)
}
}

impl Pairs {
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 add some documentation here explaining what this is for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -113,6 +114,15 @@ pub fn pairlist(item: TokenStream) -> TokenStream {
pairlist::pairlist(item)
}

/// Create a List R object from a list of name-value pairs.
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be good to mention here the potential for a panic when the input data is of the wrong format, and point users to the safer function interface instead.

@@ -63,6 +65,22 @@ impl List {
res.set_names(names).unwrap().as_list().unwrap()
}

/// Build a list using spearate names and values iterators.
/// Used by the list! macro.
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 add a use case demonstration here?

@andy-thomason
Copy link
Contributor Author

Thansk for all the feedback.

I'm going to merge it anyway for fear of it getting stale.

We should absolutely not expect it to panic, but R may have other ideas (maybe reserved names and such like).

We could also have integers![] doubles![] data_frame![] and logicals![] macros analagous to vec![].

@andy-thomason andy-thomason merged commit 2ed69ed into master Nov 23, 2021
@andy-thomason andy-thomason deleted the better-list-macro branch November 23, 2021 09:56
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

3 participants