Skip to content

Consistent ... handling#655

Open
hadley wants to merge 7 commits into
mainfrom
new-object-list
Open

Consistent ... handling#655
hadley wants to merge 7 commits into
mainfrom
new-object-list

Conversation

@hadley
Copy link
Copy Markdown
Member

@hadley hadley commented May 27, 2026

@hadley hadley requested a review from t-kalinowski May 28, 2026 15:23
@hadley
Copy link
Copy Markdown
Member Author

hadley commented May 29, 2026

For consistency we should do this in set_props() and convert() too.

@hadley hadley removed the request for review from t-kalinowski May 29, 2026 13:20
@hadley hadley changed the title Allow object construction with a list Consistent dots handling May 29, 2026
@hadley hadley changed the title Consistent dots handling Consistent ... handling May 29, 2026
@hadley
Copy link
Copy Markdown
Member Author

hadley commented May 29, 2026

Use stop2() when available.

@hadley hadley requested a review from t-kalinowski May 29, 2026 17:35
Copy link
Copy Markdown
Member

@t-kalinowski t-kalinowski left a comment

Choose a reason for hiding this comment

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

I think it's a fine idea to rename .parent to _parent, and similar.

I'm more ambivalent on splice_dots(), as implemented. It forces promises, and I think the name is misleading.

Also, my experience with reticulate::tuple() is that conveniently unpacking a list is sometimes quite a mental tax in practice, since, when writing against it, you're always guessing or trying to anticipate whether an argument may or may not be unpacked. Eventually, you come to the conclusion that the only reliable way to use it is with tuple(list(...)).

Another pattern I've seen sometimes, and kind of like, is to do something like this:

new_object <- function(.object, ..., .props = list(...)) {}

edit: just saw that you've already suggested the same in #497 (comment)

Comment thread R/convert.R
# `from` is a base or S3 object; pass it as `.data` to the constructor
return(to(.data = from, ...))
user_args$.data <- from
return(do.call(to, user_args))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This approach now forces ..., which will break any convert methods that want to introspect or delay evaluation of ....

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That's true, but it's not a change: check out the old line 152 below.

(I mean now we do force it for this very specific case, but that's only available in the dev version, so it's not a breaking change).

Comment thread R/utils.R
# Collect `...` into a named list. As a convenience, a single unnamed list is
# spliced in so its elements become the values, making it easy to supply
# values programmatically. All values must be named.
splice_dots <- function(..., error_call = sys.call(-1)) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this needs a better name. Maybe collect_dots()?

#' with property names supplied in `...`; see [new_property()] for details.
#' @param ... Name-value pairs of properties to set. As a convenience, you can
#' supply a single unnamed list instead of individual name-value pairs.
update_props <- function(`_object`, ...) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reading through this skill, I can't help but wonder, should set_props() simply take two arguments and we can avoid all this pain by simply removing the potential for name clashes?

set_props <- function(object, props) {} # where props is a named list

@hadley
Copy link
Copy Markdown
Member Author

hadley commented May 29, 2026

In general, I am also in favour of more explicit unpacking, but this is an idiom that's used elsewhere in base R (e.g. stop()), and I don't think it's such a common need that it's worth adding an additional argument.

Similarly, in an ideal world, we wouldn't force the dots so early, but in all the existing use cases they were already forced at some point, and I don't think we've ever considered NSE for property setters, and I doubt we'd want to do the work to fully flesh that out.

@hadley
Copy link
Copy Markdown
Member Author

hadley commented May 30, 2026

@lawremi do you have any opinions here? Are there patterns in base/methods that you think we should copy?

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.

Constructors: Using rlang::inject with new_object() set_props() fails when setting property named object

2 participants