-
-
Notifications
You must be signed in to change notification settings - Fork 419
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
Add style guide #1894
Add style guide #1894
Conversation
This PR should not be merged until we agree about the contents of the style guide and re-format the code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work!
Thanks for taking the time to put this together!
1 | ||
2 | ||
3 | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally disagree about this syntax for multiline arrays - my preferred style is:
let ns = [as USize:
1
2
3
]
However, I think @sylvanc cancels me out on this 🙈
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like @jemc style
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Me too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sylvan likes the opposite of Joe.
Sean doesn't care that much. Sean is good with whatever.
I suggest rock, paper, scissors between Theo and Joe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really prefer the one in the guide, as it matches other functional languages (F#, OCaml, ML) and the middle one especially (because the brackets line up).
STYLE_GUIDE.md
Outdated
|
||
// Not OK | ||
{ (a: USize, b: USize): USize => a + b } | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to give some guidance on multiline lambdas as well, though I'd be happy to add it as a followup PR if you wanted to go ahead and merge this without that detail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More examples for this have been added.
if cond then e1 else e2 end | ||
``` | ||
|
||
- Match expression cases are __not__ indented. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be a bit misleading - it might be read as implying that match expression cases with multiple lines of body should not be indented, and I think we agree that they absolutely should.
We probably need an example showing this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another example for this has been added.
STYLE_GUIDE.md
Outdated
// Not OK | ||
{(a: USize, b: USize): USize => | ||
a + b | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either way, it should be consistent between lambdas, array literals, union types, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I disagree about that - I don't think a lambda is in the same category as the other two.
In part because it will be quite common for lambdas to become rather complex by comparison, with other levels of nested indentation. Arrays can technically contain arbitrarily complex blocks of code, but in practice I think any nested levels of indentation would be quite rare. In contrast, nested levels of indentation are quite common in lambdas.
Here's an example of a lambda that isn't really that complex conceptually, but due to the nested levels of indentation, using the "same line" closing bracket strategy would look quite awkward:
rs.next({(p: zmq.SocketPeer, m: zmq.Message)(rs) =>
if m.size() > 0
peers = state.peers()
for peer in peers.values()
peer.send(recover zmq.Message.>append(m).>push("S") end)
end
end
}
Just imagine how it would look with a large match
block thrown in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd argue that it's more important for lambda to be stylistically consistent with other constructs that are large blocks of sequential code, like if
, while
, for
, etc.
STYLE_GUIDE.md
Outdated
- Blank lines between __one-line__ functions or primitives may be omitted if they are related. | ||
|
||
```pony | ||
primitive Red fun apply(): U32 => 0xFF0000FF |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unless alignment is part of the spec, i think this example shouldn't have the lining up
|
||
### Line Length | ||
|
||
The maximum line length is 80 columns. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has there been any discussion of widening this limit to 100 columns? While I understand not letting lines get too wide, 80 always seems so narrow to me. I find 100 to be a sweet spot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outside of the stdlib, that's fine of course. For the stdlib, 80 works everywhere without line wrapping problems. This is very useful on some displays - and even more often when I want to display two files side by side on a laptop :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do agree that a modest max column limit makes the code easier to read (less blank area) and easier to compare side by side. But do you really have displays that you use for this that can't show 100x2 columns?
I just wanted to get my 2¢ in before it was too late, but I'll stop whining if no one else prefers 100.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use only half of my laptop display for the text editor, so I can usually see about 76 columns without scrolling :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
80! and yes my display does not do 100x2 with the font size i find comfortable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, 80 it is. I've given in and always wear my readers when on the computer, which then lets me use a 10pt font on my retina 15" MacBook Pro to get about 300 columns across the screen. But I guess I'm an outlier.
|
||
### Blank Lines | ||
|
||
- One blank line is placed between top-level declarations such as classes, primitives, actors, etc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find that having the same one-line gap between functions and classes can cause the classes to get lost a bit. Especially since there is no end
on functions and classes.
STYLE_GUIDE.md
Outdated
end | ||
``` | ||
|
||
### Function Declarations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be Function Definitions? Or is that just a C/C++ distinction?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also mention that this is for new
and be
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe say "method" instead of "function"? We use method to mean new/fun/be, generally. Definition vs declaration is a distinction in many languages (not just C/C++), but not in Pony.
``` | ||
|
||
- Multiline function parameters are each listed on a separate line. The return type preceded by a `:` is placed at the same indentation level followed by a question mark (if the function is partial). The `=>` is placed on a separate line between the parameter list and the function body at the same indentation level as the `fun` keyword. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about a case where the parameters all fit on one line, but then the return type has to be wrapped? Would something like this be OK?
fun tag _init(typ': ValueType, default': (Value | None))
: (ValueType, Value, Bool) ?
=>
// ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good example. That's exactly what I do :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is what we do in the sendence code base as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example added
### Whitespace | ||
|
||
- Use spaces around binary operators and after commas, colons, and semicolons. Do not put spaces around brackets or parentheses. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about the =
used to defined default parameter values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spaces around those too please :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Theodus can you update to include that?
Please no force push that will kill off comments early though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example added
Here are a couple areas of the style guide I thought could use some clarification, as I came across styling some code I wrote:
match s
| "string1" | "string2" | "string3" | "string4" | "string5" |
"string6" | "string7" | "string" => Some()
| "other" => Other()
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome and @Theodus is awesome.
1 | ||
2 | ||
3 | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really prefer the one in the guide, as it matches other functional languages (F#, OCaml, ML) and the middle one especially (because the brackets line up).
|
||
### Line Length | ||
|
||
The maximum line length is 80 columns. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outside of the stdlib, that's fine of course. For the stdlib, 80 works everywhere without line wrapping problems. This is very useful on some displays - and even more often when I want to display two files side by side on a laptop :)
- Fields have no blank lines between them. | ||
- Functions are separated from other members by one line. | ||
|
||
```pony |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These all need indentation :)
### Whitespace | ||
|
||
- Use spaces around binary operators and after commas, colons, and semicolons. Do not put spaces around brackets or parentheses. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spaces around those too please :)
STYLE_GUIDE.md
Outdated
|
||
```pony | ||
if cond1 then e1 | ||
elif cond2 then e2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
elseif
STYLE_GUIDE.md
Outdated
|
||
if cond1 then | ||
e1 | ||
elif cond2 then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
elseif
STYLE_GUIDE.md
Outdated
end | ||
``` | ||
|
||
### Function Declarations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe say "method" instead of "function"? We use method to mean new/fun/be, generally. Definition vs declaration is a distinction in many languages (not just C/C++), but not in Pony.
``` | ||
|
||
- Multiline function parameters are each listed on a separate line. The return type preceded by a `:` is placed at the same indentation level followed by a question mark (if the function is partial). The `=>` is placed on a separate line between the parameter list and the function body at the same indentation level as the `fun` keyword. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good example. That's exactly what I do :)
@Theodus this is fantastic. Thank you! @patternspandemic good call! |
Fixes formatting of I32.min_value(). TODO: the u32 and u64 funs in _format_int.pony could probably be largely re-unified. Update formatting to follow style guide proposal (ponylang#1894). Fixes: ponylang#1920
offset: USize = 0, | ||
nth: USize = 0, | ||
predicate: {(box->A!, box->A!): Bool} val = | ||
{(l: box->A!, r: box->A!): Bool => l is r }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this wrapping seems very, weird
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me it seems that this is the best way to be consistent with the "hanging" style for assignments with a large right-hand-side. That is, a parameter with a large default value should have the same style as such an assignment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cant say i disagree with that. it still seems a little weird.
Fixes formatting of I32.min_value(). TODO: the u32 and u64 funs in _format_int.pony could probably be largely re-unified. Update formatting to follow style guide proposal (ponylang#1894). Fixes: ponylang#1920
Fixes formatting of I32.min_value(). TODO: the u32 and u64 funs in _format_int.pony could probably be largely re-unified. Update formatting to follow style guide proposal (ponylang#1894). Fixes: ponylang#1920
Fixes formatting of I32.min_value(), I16.min_value(), etc. TODO: the various type-specific funs in _format_int.pony could probably be largely re-unified. Update formatting to follow style guide proposal (ponylang#1894). Fixes: ponylang#1920
Fixes formatting of I32.min_value(), I16.min_value(), etc. TODO: the various type-specific funs in _format_int.pony could probably be largely re-unified. Update formatting to follow style guide proposal (ponylang#1894). Fixes: ponylang#1920
Fixes formatting of I32.min_value(), I16.min_value(), etc. TODO: the various type-specific funs in _format_int.pony could probably be largely re-unified. Update formatting to follow style guide proposal (ponylang#1894). Fixes: ponylang#1920
Fixes formatting of I32.min_value(), I16.min_value(), etc. TODO: the various type-specific funs in _format_int.pony could probably be largely re-unified. Update formatting to follow style guide proposal (ponylang#1894). Fixes: ponylang#1920
[skip ci]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed on the sync call, I'm relenting on multiline arrays.
Thanks for tackling this, @Theodus!
This PR adds a style guide for the standard library and re-formats the standard library code to conform to it.
[skip ci]