An R Style Guide written in bookdown (https://github.com/rstudio/bookdown).
tidyverse / style Goto Github PK
View Code? Open in Web Editor NEWThe tidyverse style guide for R code
Home Page: https://style.tidyverse.org
License: Other
The tidyverse style guide for R code
Home Page: https://style.tidyverse.org
License: Other
An R Style Guide written in bookdown (https://github.com/rstudio/bookdown).
I was wondering whether it would make sense to extend the style guide with regard to roxygen2
documentation, i.e. by giving guidelines on roxygen2
-specific topics like :
code_style_font
(only for functions, for variables, function arguments, TRUE / FALSE, NA etc.)?function_call()
or function_call
when referring to a function.I note that some conventions seem to exist, but even then it would make sense to turn the implicit into the explicit.
In Spacing section of "Syntax" chapter there is a guideline "Place a space before (
when its used with a keyword like if
, for
or function
". Is presence of function
here a typo? Because it doesn't seem right. Maybe it should be "..., but not with function
"?
Should NAMESPACE
and DESCRIPTION
be surrounded by backticks when referenced in markdown?
Currently we're inconsistent. In the roxygen vignettes (e.g. Package namespace) we use backticks, but we do so inconsistently in NEWS for same.
This might fall under a broader umbrella, and I'm missing which one.
i.e. code in scripts vs. code in packages
I believe R4DS does not use codefont
for package names. Instead uses bolding in the first mention and regular text later on. Is this the recommended way to format how package names appear in writing? It would be useful to make a recommendation about this at http://style.tidyverse.org/code-documentation.html#code-font.
Formatting of cran-comments.md and probably how best to interact with CRAN in general as well.
Copying what adv-r does
i.e. :
and above don't have spaces
The exception to the rule is prefix ~
, which we treat consistently with prefix +
and -
.
In the introduction of the style guide, it says
To apply this style guide automatically, use lintr.
Should we add a reference to styler, e.g. change the sentence to
To apply this style guide automatically, use lintr for static code analysis and styler for reformatting code.
Or something like that?
iris %>%
group_by(Species) %>%
summarise(
Sepal.Length = mean(Sepal.Length),
Sepal.Width = mean(Sepal.Width),
Sepcies = n_distinct(Species)
) %>%
select(Species)
compare to
iris %>%
group_by(Species) %>%
summarise(Sepal.Length = mean(Sepal.Length),
Sepal.Width = mean(Sepal.Width),
Species = n_distinct(Species)) %>%
select(Species)
Matter of opinion, but I was just wondering what are the merits of the first one, esp. given that the second one is consistent with how long line function args are usually written.
I think that the actual approach is to use usethis::use_version
for version numbers in x.y.z
. But there are some package which follow the x.y.z.9000
style (like sessionInfo).
Perhaps this is tied to the release cycle of each package, which also seem inconsistent, or how many users install from CRAN, a formal release, and how many from Github.
Maybe a new section under Documentation might be worth ?
In style guide:
https://github.com/tidyverse/style/blob/master/07-errors.Rmd#L102-L104
dplyr::filter(iris, Species = "setosa")
#> Error: Filter specifications must be named
#> Did you mean `Species == "setosa"`?
Current tidyverse/dplyr@4c2487a
dplyr::filter(iris, Species = "setosa")
#> Error: `Species` (`Species = "setosa"`) must not be named, do you need `==`?
Created on 2018-05-14 by the reprex package (v0.2.0).
I can change the style guide example, or move this to dplyr, just not sure which to doβ¦
In a PR and a subsequent issue reviewed by @krlmlr, I was advised to avoid sub assignment when possible. I think I might be reasonable to extend the style guide in this regard, namely section 2.6.
# Good
pd <- pd %>%
indent_round(pd, indent_by = 2) %>%
mutate(child = map(child, indent_round_nested)
# Bad
pd <- indent_round(pd, indent_by = 2)
pd$child <- map(pd$child, indent_round_nested)
What do you think?
I couldn't find any advice in the style guide about empty lines. Maybe you want to add some information on that topic?
Questions that could be interesting in my opinion are for example:
Regarding the third question, an example where empty lines inside a function call could be considered helpful is this:
greetings_long <- c(
paste0(
"Welcome back ",
name,
"!"
),
paste0(
"Hello ",
name,
". How are you?"
),
paste0(
"Aren't you ",
name,
"? Nice to meet you!"
)
)
It might be useful to mention ngettext()
in the Errors section, as a good way to handle pluralized message forms.
NAs found at 1,000,000 locations: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...
I think it would be useful to add an example under section 2.2 Spacing on how spacing should be done around !!!
and !!
. In the programming with dyplr vignette, there is no spacing around those operators whereas there is spacing around them in the help file for rlang::quasiquotation
(up-to-date package version 0.1.2.9000).
Reference: r-lib/styler#110.
@hrbrmstr had some good pointers re pipes in his RStudio::conf talk, e.g. don't use the pipe for just one function (mtcars %>% str()
), piping data into ggplot is probably not a good idea (breaks the pipes should be 'atomic' rule, etc.
In Assignment section of "Pipe" chapter there is a guideline "Use a separate line for the target of the assignment followed by <-
.". However, I think it is not intuitive and used very rarely by community compared to placing source object after the <-
. There are also examples in R4DS of this style.
Maybe it is better to change this?
Let's decide which of these we want:
Option A: class names ARE NOT formatted as code:
A tibble will have class tbl_df ...
Thedata.frame()
function returns an object of class data.frame ...
frame_matrix()
allows you to create a matrix by laying the data out in rows ...
predict()
expects an lm or glm object as input ...
Option B: class names ARE formatted as code:
A tibble will have class
tbl_df
...
Thedata.frame()
function returns an object of classdata.frame
...
frame_matrix()
allows you to create amatrix
by laying the data out in rows ...
predict()
expects anlm
orglm
object as input ...
Context: beefing up the roxygen2 docs around cross-linking help topics. Want to provide advice that covers our recommended treatment. So imagine all the classes in question (tbl_df, data.frame, matrix, lm, glm) are linked to the associated help topic.
Other subdomains such as https://ggplot2.tidyverse.org or the main site https://www.tidyverse.org work, but this one returns a certificate for a different site.
e.g. # In development
something like that
iris %>%
group_by(Species) %>%
summarize_if(is.numeric(), mean) %>%
ungroup %>%
gather(measure, value, -Species) %>%
arrange(value)
returns
Error in is.numeric() :
0 arguments passed to 'is.numeric' which requires 1
Correct code should be:
iris %>%
group_by(Species) %>%
summarize_if(is.numeric, mean) %>%
ungroup() %>%
gather(measure, value, -Species) %>%
arrange(value)
Initially raised in: https://community.rstudio.com/t/function-argument-naming-conventions-x/7764
In a lot of tidyverse packages, function arguments are prefixed with a .
, for instance in purrr:
purrr::map
#> function (.x, .f, ...)
#> {
#> .f <- as_mapper(.f, ...)
#> .Call(map_impl, environment(), ".x", ".f", "list")
#> }
#> <environment: namespace:purrr>
As I understand it, this is to minimise ambiguity/clashes with other variable names in the current R session. Is this the preferred style for naming function arguments? Are there times when this isn't the preferred style?
Is it worth adding a note in the functions
section clarifying this?
Current tidyverse comment style:
#
for any comment
My suggestion:
##
for a full line comment
#
for a comment on a code line
Example:
## Example code
y <- 3 + 2 # I don't have imagination
Rationale:
Note: Jim Hester was ok to accept my PR to allow ##
in commented_code_linter
in the lintr package (see r-lib/lintr#301). So lintr is now happy with ##
full line comments π
Chapter 6 of the style guide is mainly focusing on documenting functions. However, there are other things that can - and probably should - be documented as well, e.g. datasets, classes, etc. Maybe you can add some information on documenting these?
Just to show one example:
In section 6.2 the style guide says:
For the title, describe concisely what the function does in the very first line of your function documentation. Titles should use sentence case but not end with a full stop.
Although it seems likely, it is not 100% clear whether the title of dataset or class documentation should also use sentence case and not end with a full stop. And it's also not stated in the guide what exactly should be described in the title for datasets and classes.
Is it possible to include suggestions/rules for color usage and (possibly) some hints on the implementation?
Not sure if this belongs here or http://r-pkgs.had.co.nz
Naming files, e.g. if function is foo_bar()
is the file R/foo_bar.R
or R/foo-bar.R
. Are you allowed to define foo_yo()
in here too?
Relationship between name of file where a function is defined and the (name of) test file in which it is tested.
tryCatch(
message = function(c) "There",
{
message("Here")
stop("This code is never run!")
}
)
c
, short for conditioncf http://style.tidyverse.org/functions.html#return
I think it's good practice to put it on a newline so it's not hidden behind the if condition:
# Good
find_abs <- function(x, y) {
if (x > 0) {
return(x)
}
x * -1
}
# Bad
find_abs <- function(x, y) {
if (x > 0) return(x)
x * -1
}
It's not a style issue.
Should add a section about documenting internal functions which have no Rd files and are only intended to be read by other developers.
Recommendation is to use #'
comments per usual, but with @noRd
tag. See Hadley's comment here.
In the styler project, we came across the question whether the rule to
break the line after
(
if a function call does not fit on one line
applies to all functions, or whether switch()
, ifelse()
and friends are an exception to it In other words, whether
switch(on_same_line,
next_line,
another_new_line
)
Is preferred over
switch(
on_next_line,
next_line,
another_new_line
)
Another (potential) candidate is case_when()
.
Reference: krlmlr/rlang#1 (comment), r-lib/styler#152.
Seems like there is inconsistent spacing after function(x, y)
within the # Good
example for https://github.com/tidyverse/style/blob/master/03-functions.Rmd#return
# Good
find_abs <- function(x, y){
if (x > 0) return(x)
x * -1
}
add_two <- function(x, y) {
x + y
}
Should find_abs <- function(x, y){
be replaced with find_abs <- function(x, y) {
?
Let's recommend how to write @seealso
s.
I dither over continuing the sentence "See also ... this_cool_thing for more info. Another_cool_thing does something else related." and writing individually self-contained sentences like so:
Perhaps it depends on whether you are just listing functions, writing one sentence, writing several sentences?
The style guide says in section 2.2:
Place a space before
(
, except when itβs part of a function call.
I suspect this was meant to apply only to language keywords like, if
, for
, and so on.
For example, in the same section
average <- mean((feet / 12) + inches, na.rm = TRUE)
is listed as a "good" code example, although there is no space before the second (
.
Furthermore, still in the same section the guide also says
Do not place spaces around code in parentheses
which doesn't really work together with putting spaces before (
s either.
While it's useful to separate printed output from messaging, message()
comes with a big downside: messages are printed to stderr,
How come I can see the chapter on error messages published under http://style.tidyverse.org/
although #53 is not yet merged into master?
http://style.tidyverse.org/error-messages.html
We should have a standard, documented syntax for describing that a function argument uses tidy evaluation (or just quasiquotation).
e.g. tidyverse/dplyr#3953
In styler, we were wondering whether it would make sense to add a rule to the style guide that says
If you use infix operators (such as
|
,&
etc.) and you decide to break the line around them, the
line break should occur after the infix operator, not before it.
# good
if (a_long_condition & and_another_long_condition &
one_more) {
# do something
}
# bad
if (a_long_condition & and_another_long_condition
& one_more) {
# do something
}
Or whether conditions should not be that long anyways so the problem does not occur and / or it is an edge case not worth mentioning.
In any case, we would probably implement a rule in styler that moves the infix operator one line up to change # bad
above to # good
.
cc: @krlmlr.
In this dplyr PR, it was proposed to change the rules for spacing after !!
to be zero spaces and to remove the rule for !!!
from the style guide for now since the style has not yet been decided on. In addition, the section on operator precedence seems to become redundant with the new operator precedence in rlang 0.2.0
or at least needs adaption. If we drop the section, the chapter tidyeval will only have one section, so I think it would be legit to move the remarks on bang syntax to the chapter on syntax, in particular to the section on spacing.
Would you consider it within the scope of the tidyverse
style guide to cover some of your suggestions and conventions regarding each of R's object oriented programming paradigms?
With your approval, I'd be happy to get this going with a PR based on some of the content from section 3 of Adv-R.
I find students under-utilize RStudio's features for code formatting: Reflow Comment, Reindent Lines, Reformat Code, etc.. Maybe add some concrete suggestions about this when you mention lintr for checking?
The use of different file encodings is a root of headache for both package developers and end-users, hence, @krlmlr proposes to promote UTF-8 as the encoding to use. Is a paragraph on that welcomed in the tidyverse style guide?
Migrated from r-lib/styler#376 (comment).
Use call. = FALSE
Surround names and expressions in `
, surround strings in '
, ensure paths end in /
Grammatical form
Ideally show both what was supplied (since argument often computed and not immediately accessible) and what was expected
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.