Skip to content

Remove ellipsis from theme #1762

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

Merged
merged 12 commits into from
Sep 23, 2016
Merged

Conversation

thomasp85
Copy link
Member

Fixes #1744

elements <- as.list(environment())
elements$complete <- NULL
elements$validate <- NULL
elements <- elements[lapply(elements, class) != "name"]
Copy link
Member Author

Choose a reason for hiding this comment

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

I would love some feedback on whether this is the best way to capture all non-missing arguments as evaluated values...?

#' @param rect all rectangular elements (\code{element_rect})
#' @param text all text elements (\code{element_text})
#' @param title all title elements: plot, axes, legends (\code{element_text};
#' inherits from \code{text})
Copy link
Member

Choose a reason for hiding this comment

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

Can you please indent the second and subsequent lines?

elements <- c(as.list(environment()), list(...))
elements$complete <- NULL
elements$validate <- NULL
elements <- elements[lapply(elements, class) != "name"]
Copy link
Member

Choose a reason for hiding this comment

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

Why is this necessary? Regardless, it would be cleaner to use vapply() + is.name()

Copy link
Member Author

Choose a reason for hiding this comment

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

If we don't remove name elements the theme validation will complain

Copy link
Member

Choose a reason for hiding this comment

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

But why? Where do those name elements come from?

Copy link
Member Author

Choose a reason for hiding this comment

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

these are missing arguments - they exist in the environment and is added to the list as name objects

plot.caption, plot.margin, strip.background, strip.text,
strip.text.x, strip.text.y, strip.switch.pad.grid,
strip.switch.pad.wrap, ..., complete = FALSE, validate = TRUE) {
elements <- c(as.list(environment()), list(...))
Copy link
Member

Choose a reason for hiding this comment

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

Hmmmm, I don't like this but I don't see a better way except creating the massive named list by hand (which seems likely to be error prone).

Copy link
Member

Choose a reason for hiding this comment

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

I would really prefer if this was extracted into a separate function and gained a couple of safe guards:

find_args <- function(...) {
  env <- parent.frame()
  args <- names(formals(sys.function(sys.parent(1))))

  vals <- c(as.list(env)[args], list(...))
  vals <- vals[!vapply(vals, identical, quote(expr = ), FUN.VALUE = logical(1))]
  vals
}

f <- function(a = 1, b = 2, c = 3, d, e, abcdefasdfgasdfasdfasd) {
   find_args()
}
f(10, abc = 10)

Copy link
Member

Choose a reason for hiding this comment

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

This is slightly more elegant:

find_args <- function(...) {
  env <- parent.frame()
  args <- names(formals(sys.function(sys.parent(1))))

  vals <- mget(args, envir = env)
  vals <- vals[!vapply(vals, identical, quote(expr = ), FUN.VALUE = logical(1))]

  c(vals, list(...))
}

Copy link
Member

@hadley hadley Sep 20, 2016

Choose a reason for hiding this comment

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

is_missing_arg <- function(x) identical(x, quote(expr = )))

Copy link
Member

@hadley hadley Sep 20, 2016

Choose a reason for hiding this comment

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

And even better:

find_args <- function(...) {
  env <- parent.frame()
  args <- names(formals(sys.function(sys.parent(1))))

  vals <- mget(args, envir = env)
  vals <- vals[!vapply(vals, is_missing_arg, logical(1))]

  modifyList(vals, list(...))
}

@hadley
Copy link
Member

hadley commented Sep 20, 2016

@wch I have vague memory you thought about this problem (capturing all arguments) a bit

@thomasp85 thomasp85 self-assigned this Sep 20, 2016
elements <- c(as.list(environment()), list(...))
elements$complete <- NULL
elements$validate <- NULL
elements <- elements[!vapply(elements, is.name, logical(1))]
Copy link
Member

@hadley hadley Sep 20, 2016

Choose a reason for hiding this comment

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

The absolutely correct check is:

elements <- elements[!vapply(elements, identical, quote(expr = ), FUN.VALUE = logical(1))]

# named .ignore
# @param ... passed on in case enclosing function uses ellipsis in argument list
# @param .ignore remove these arguments from the list
find_args <- function(..., .ignore = NULL) {
Copy link
Member

@hadley hadley Sep 21, 2016

Choose a reason for hiding this comment

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

Why not drop .ignore and just use (e.g.) complete = NULL, validate = NULL)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because validate_theme will throw an error if they are included in the list

Copy link
Member

Choose a reason for hiding this comment

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

find_args(..., complete = NULL, validate = NULL)

Copy link
Member

Choose a reason for hiding this comment

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

Then modifyList will remove them

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah - didn't think of that

@@ -56,6 +56,8 @@
* Themes are more homogeneous visually, and match `theme_grey` better.
(@jiho, #1679)

* The `theme()` constructor now has named arguments rather than ellipsis.
Copy link
Member

Choose a reason for hiding this comment

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

"This should make autocomplete substantially more useful"

@codecov-io
Copy link

Current coverage is 66.18% (diff: 100%)

Merging #1762 into master will increase coverage by 0.04%

@@             master      #1762   diff @@
==========================================
  Files           157        157          
  Lines          5112       5119     +7   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
+ Hits           3381       3388     +7   
  Misses         1731       1731          
  Partials          0          0          

Powered by Codecov. Last update 70ae16c...ecf92c6

# Get all arguments in a function as a list. Will fail if an ellipsis argument
# named .ignore
# @param ... passed on in case enclosing function uses ellipsis in argument list
# @param .ignore remove these arguments from the list
Copy link
Member

Choose a reason for hiding this comment

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

This needs to be removed now, other LGTM

@thomasp85 thomasp85 merged commit e1c800d into tidyverse:master Sep 23, 2016
@lock
Copy link

lock bot commented Jan 18, 2019

This old issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with reprex) and link to this issue. https://reprex.tidyverse.org/

@lock lock bot locked and limited conversation to collaborators Jan 18, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants