-
Notifications
You must be signed in to change notification settings - Fork 111
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
Multi-argument function call as argument to another function #238
Comments
I don't think the guide should weigh in on this. both are fine in different circumstances and I'm not sure it's worth defining detailed rules for which is which. FWIW I typically prefer the first style. |
What about it do you prefer? |
adding vertical and horizontal whitespace does not come for free. it also presents tradeoffs. here I honestly don't see the confusion you do -- the case_when arguments are further indented than mutate(). this may not always be the case / can be up to taste. I personally don't think the style guide should weigh in. Evaluation can be done case-by-case between code author & reviewer. |
BTW, I often choose to write code like this even more succinctly: tibble(int = 1:70) |>
mutate(response = case_when(
int %% 35 == 0 ~ "fizz buzz",
int %% 5 == 0 ~ "fizz",
int %% 7 == 0 ~ "buzz",
.default = as.character(int)
)) The style is also guide-compliant and again, contextually preferable (or at least, unproblematic). |
You mentioned that this formatting style is contextually dependent, and I agree entirely. However, I want to elaborate on the nuances. In general, this succint style only works if the function ( I also agree that for the specific example you showed, this style is perfectly fine and unproblematic. Examples: library(tidyverse)
# Ok and succinct
tibble(int = 1:70) |>
mutate(response = case_when(
int %% 35 == 0 ~ "fizz buzz",
int %% 5 == 0 ~ "fizz",
int %% 7 == 0 ~ "buzz",
.default = as.character(int)
))
# Bad
tibble(int = 1:70) |>
mutate(response = case_when(
int %% 35 == 0 ~ "fizz buzz",
int %% 5 == 0 ~ "fizz",
int %% 7 == 0 ~ "buzz",
.default = as.character(int)
), .before = int)
# Bad
tibble(int = 1:70) |>
mutate(response = case_when(
int %% 35 == 0 ~ "fizz buzz",
int %% 5 == 0 ~ "fizz",
int %% 7 == 0 ~ "buzz",
.default = as.character(int)
),
.before = int
)
# Good
tibble(int = 1:70) |>
mutate(
response = case_when(
int %% 35 == 0 ~ "fizz buzz",
int %% 5 == 0 ~ "fizz",
int %% 7 == 0 ~ "buzz",
.default = as.character(int)
),
sign = case_when(
int > 0 ~ "positive",
int < 0 ~ "negative",
.default = "zero"
),
.before = int
) Another example where this pattern appears and is the undocumented recommended (?) style: # Good
testthat::test_that("Test context", {
test_var <- 1 + 1
expect_equal(test_var, 2)
}) In summary, the single-argument piping style can be concise and perfectly acceptable for simple cases, but it's important to recognize where it won't work. Making these caveats more explicit in the guide could help practitioners avoid confusion and use this stylistic choice wisely. |
Here are two examples (based on first example from documentation for
case_when()
):In the first case, the name
response
obscures the fact that the arguments that follow belong tocase_when()
. This becomes much worse as the number of arguments and levels of nesting increase, so I would far preferto
Thoughts? Could this be added to the guide?
The text was updated successfully, but these errors were encountered: