Skip to content

Commit 7080d2a

Browse files
Enhance "Why Non-Invasive?" documentation with detailed examples
Co-authored-by: felix-andreas <[email protected]>
1 parent cda5472 commit 7080d2a

File tree

5 files changed

+173
-2
lines changed

5 files changed

+173
-2
lines changed

crates/roughly/tests/format/formatter.template.md

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,78 @@ The formatter follows these key principles:
3030

3131
R is an expression-based language with a strong focus on numerical computing and data analysis. Unlike many other programming languages, R code is often written interactively and exploratively, where preserving the original intent and structure of expressions is crucial for readability and debugging.
3232

33-
The non-invasive approach means roughly respects your existing line breaks and won't arbitrarily split expressions that you've chosen to keep on one line. This is particularly important in R because:
33+
The non-invasive approach means roughly respects your existing line breaks and won't arbitrarily split expressions that you've chosen to keep on one line. **Non-invasive formatting tries to minimize the amount of line-breaks not set by the programmer** by following these key principles:
34+
35+
- **Single line expressions are never broken into multiple lines** (with the exception of loops like `for`, `while`, `repeat`, because they don't yield useful values and can only perform side effects, so they are not normal expressions in that sense)
36+
- **Both hugging and not hugging is allowed** for function calls and other constructs
37+
- **Preserves programmer intent** regarding line structure and formatting choices
38+
39+
This is particularly important in R because:
3440

3541
- **Data analysis workflows**: Short, expressive one-liners are common and meaningful
3642
- **Interactive development**: Code is often built incrementally, and forced line breaks can disrupt the flow
3743
- **Mathematical expressions**: Complex formulas are often more readable when kept compact
3844
- **Functional style**: R's functional nature benefits from preserving the structure of nested calls
3945

46+
#### Why This Matters for Numerical Computing
47+
48+
R is a numerical language, and numerical expressions tend to get ugly when broken up by line length limits. Consider this mathematical expression:
49+
50+
```r
51+
# non_invasive_numerical_example : format
52+
# Without non-invasive formatting, this compact expression:
53+
n <- 1 + (length(replacement_id) - 1) * (vectorToSearch == valueTypeToReplace)
54+
55+
# Might get broken up into this less readable form:
56+
# n <- 1 +
57+
# (length(replacement_id) - 1) *
58+
# (vectorToSearch == valueTypeToReplace)
59+
```
60+
61+
This forced line breaking can lead to several problems:
62+
- People might use shorter, less descriptive variable names just to fit expressions on one line
63+
- Intermediate results might be stored in variables that have no meaningful purpose or don't correspond to established mathematical formulas
64+
- The mathematical relationship becomes harder to understand
65+
66+
#### Consistency Between Related Lines
67+
68+
Sometimes you want consistency between multiple consecutive lines, especially when they follow the same pattern but have slight variations. For example, if you have two lines that only differ by a prefix or suffix, it's better to keep them both on single lines for easy comparison:
69+
70+
```r
71+
# consistency_example : format
72+
# This is easier to read and compare:
73+
start <- camera_origin_start - (focus_dist * forward_start) - 0.5 * view_width * right_start + 0.5 * view_height * up_start
74+
end <- camera_origin_end - (focus_dist * forward_end) - 0.5 * view_width * right_end + 0.5 * view_height * up_end
75+
76+
# Than this inconsistent formatting where only one line is broken:
77+
# start <- camera_origin_start - (focus_dist * forward_start) - 0.5 * view_width * right_start
78+
# + 0.5 * view_height * up_start
79+
# end <- camera_origin_end - (focus_dist * forward_end) - 0.5 * view_width * right_end + 0.5 * view_height * up_end
80+
```
81+
82+
#### Switch Statement Example
83+
84+
The same principle applies to switch statements where one arm might have a longer expression. Non-invasive formatting keeps consistency across all arms:
85+
86+
```r
87+
# switch_consistency_example : format
88+
# Consistent formatting across all switch arms:
89+
result <- switch(method,
90+
"simple" = calculate_simple_stats(data),
91+
"complex" = perform_advanced_statistical_analysis_with_multiple_parameters(data, alpha = 0.05, method = "robust"),
92+
"default" = get_basic_summary(data)
93+
)
94+
95+
# Rather than breaking only the longer arm:
96+
# result <- switch(method,
97+
# "simple" = calculate_simple_stats(data),
98+
# "complex" = perform_advanced_statistical_analysis_with_multiple_parameters(
99+
# data, alpha = 0.05, method = "robust"
100+
# ),
101+
# "default" = get_basic_summary(data)
102+
# )
103+
```
104+
40105
## Formatting Rules
41106

42107
Roughly applies specific formatting rules to different R code constructs. The formatter analyzes the abstract syntax tree to make intelligent decisions about spacing, line breaks, and indentation.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
source: crates/roughly/tests/test_format.rs
3+
expression: code
4+
---
5+
# This is easier to read and compare:
6+
start <- camera_origin_start - (focus_dist * forward_start) - 0.5 * view_width * right_start + 0.5 * view_height * up_start
7+
end <- camera_origin_end - (focus_dist * forward_end) - 0.5 * view_width * right_end + 0.5 * view_height * up_end
8+
9+
# Than this inconsistent formatting where only one line is broken:
10+
# start <- camera_origin_start - (focus_dist * forward_start) - 0.5 * view_width * right_start
11+
# + 0.5 * view_height * up_start
12+
# end <- camera_origin_end - (focus_dist * forward_end) - 0.5 * view_width * right_end + 0.5 * view_height * up_end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
source: crates/roughly/tests/test_format.rs
3+
expression: code
4+
---
5+
# Without non-invasive formatting, this compact expression:
6+
n <- 1 + (length(replacement_id) - 1) * (vectorToSearch == valueTypeToReplace)
7+
8+
# Might get broken up into this less readable form:
9+
# n <- 1 +
10+
# (length(replacement_id) - 1) *
11+
# (vectorToSearch == valueTypeToReplace)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
source: crates/roughly/tests/test_format.rs
3+
expression: code
4+
---
5+
# Consistent formatting across all switch arms:
6+
result <- switch(
7+
method,
8+
"simple" = calculate_simple_stats(data),
9+
"complex" = perform_advanced_statistical_analysis_with_multiple_parameters(data, alpha = 0.05, method = "robust"),
10+
"default" = get_basic_summary(data)
11+
)
12+
13+
# Rather than breaking only the longer arm:
14+
# result <- switch(method,
15+
# "simple" = calculate_simple_stats(data),
16+
# "complex" = perform_advanced_statistical_analysis_with_multiple_parameters(
17+
# data, alpha = 0.05, method = "robust"
18+
# ),
19+
# "default" = get_basic_summary(data)
20+
# )

docs/content/formatter.md

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,76 @@ The formatter follows these key principles:
3030

3131
R is an expression-based language with a strong focus on numerical computing and data analysis. Unlike many other programming languages, R code is often written interactively and exploratively, where preserving the original intent and structure of expressions is crucial for readability and debugging.
3232

33-
The non-invasive approach means roughly respects your existing line breaks and won't arbitrarily split expressions that you've chosen to keep on one line. This is particularly important in R because:
33+
The non-invasive approach means roughly respects your existing line breaks and won't arbitrarily split expressions that you've chosen to keep on one line. **Non-invasive formatting tries to minimize the amount of line-breaks not set by the programmer** by following these key principles:
34+
35+
- **Single line expressions are never broken into multiple lines** (with the exception of loops like `for`, `while`, `repeat`, because they don't yield useful values and can only perform side effects, so they are not normal expressions in that sense)
36+
- **Both hugging and not hugging is allowed** for function calls and other constructs
37+
- **Preserves programmer intent** regarding line structure and formatting choices
38+
39+
This is particularly important in R because:
3440

3541
- **Data analysis workflows**: Short, expressive one-liners are common and meaningful
3642
- **Interactive development**: Code is often built incrementally, and forced line breaks can disrupt the flow
3743
- **Mathematical expressions**: Complex formulas are often more readable when kept compact
3844
- **Functional style**: R's functional nature benefits from preserving the structure of nested calls
3945

46+
#### Why This Matters for Numerical Computing
47+
48+
R is a numerical language, and numerical expressions tend to get ugly when broken up by line length limits. Consider this mathematical expression:
49+
50+
```r
51+
# Without non-invasive formatting, this compact expression:
52+
n <- 1 + (length(replacement_id) - 1) * (vectorToSearch == valueTypeToReplace)
53+
54+
# Might get broken up into this less readable form:
55+
# n <- 1 +
56+
# (length(replacement_id) - 1) *
57+
# (vectorToSearch == valueTypeToReplace)
58+
```
59+
60+
This forced line breaking can lead to several problems:
61+
- People might use shorter, less descriptive variable names just to fit expressions on one line
62+
- Intermediate results might be stored in variables that have no meaningful purpose or don't correspond to established mathematical formulas
63+
- The mathematical relationship becomes harder to understand
64+
65+
#### Consistency Between Related Lines
66+
67+
Sometimes you want consistency between multiple consecutive lines, especially when they follow the same pattern but have slight variations. For example, if you have two lines that only differ by a prefix or suffix, it's better to keep them both on single lines for easy comparison:
68+
69+
```r
70+
# This is easier to read and compare:
71+
start <- camera_origin_start - (focus_dist * forward_start) - 0.5 * view_width * right_start + 0.5 * view_height * up_start
72+
end <- camera_origin_end - (focus_dist * forward_end) - 0.5 * view_width * right_end + 0.5 * view_height * up_end
73+
74+
# Than this inconsistent formatting where only one line is broken:
75+
# start <- camera_origin_start - (focus_dist * forward_start) - 0.5 * view_width * right_start
76+
# + 0.5 * view_height * up_start
77+
# end <- camera_origin_end - (focus_dist * forward_end) - 0.5 * view_width * right_end + 0.5 * view_height * up_end
78+
```
79+
80+
#### Switch Statement Example
81+
82+
The same principle applies to switch statements where one arm might have a longer expression. Non-invasive formatting keeps consistency across all arms:
83+
84+
```r
85+
# Consistent formatting across all switch arms:
86+
result <- switch(
87+
method,
88+
"simple" = calculate_simple_stats(data),
89+
"complex" = perform_advanced_statistical_analysis_with_multiple_parameters(data, alpha = 0.05, method = "robust"),
90+
"default" = get_basic_summary(data)
91+
)
92+
93+
# Rather than breaking only the longer arm:
94+
# result <- switch(method,
95+
# "simple" = calculate_simple_stats(data),
96+
# "complex" = perform_advanced_statistical_analysis_with_multiple_parameters(
97+
# data, alpha = 0.05, method = "robust"
98+
# ),
99+
# "default" = get_basic_summary(data)
100+
# )
101+
```
102+
40103
## Formatting Rules
41104

42105
Roughly applies specific formatting rules to different R code constructs. The formatter analyzes the abstract syntax tree to make intelligent decisions about spacing, line breaks, and indentation.

0 commit comments

Comments
 (0)