diff --git a/proposals/p0861.md b/proposals/p0861.md new file mode 100644 index 0000000000000..e961be07ae8bf --- /dev/null +++ b/proposals/p0861.md @@ -0,0 +1,216 @@ +# Naming conventions + + + +[Pull request](https://github.com/carbon-language/carbon-lang/pull/861) + + + +## Table of contents + +- [Problem](#problem) +- [Background](#background) + - [Cross-language precedent](#cross-language-precedent) + - [Carbon artifacts](#carbon-artifacts) +- [Proposal](#proposal) +- [Details](#details) + - [Constants](#constants) + - [Carbon-provided item naming](#carbon-provided-item-naming) +- [Open questions](#open-questions) +- [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals) +- [Alternatives considered](#alternatives-considered) + - [Other naming conventions](#other-naming-conventions) + - [Other conventions for naming Carbon types](#other-conventions-for-naming-carbon-types) + + + +## Problem + +The goal of this proposal is to establish naming conventions for: + +- Idiomatic Carbon code. +- Carbon-provided features, including: + - Keywords, such as `fn` or `for`. + - Type literals, such as `i32`. + - Types, such as `bool` or `String`. + +The reason for resolving this through proposal is to ensure we're headed in a +reasonably consistent path as we write early documentation and example code. + +## Background + +### Cross-language precedent + +Naming conventions are an issue frequently addressed by style guides. A few +examples of language-provided guidelines are: + +- [Effective Go](https://golang.org/doc/effective_go#names) +- [Python's PEP 8](https://www.python.org/dev/peps/pep-0008/#naming-conventions) + - Note PEP 8 offers a list of + [naming styles](https://www.python.org/dev/peps/pep-0008/#descriptive-naming-styles). +- [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/naming.html) +- [Swift's API Design Guidelines](https://swift.org/documentation/api-design-guidelines/#general-conventions) + +### Carbon artifacts + +Related issues: + +- Issue + [#543: pick names for fixed-size integer types](https://github.com/carbon-language/carbon-lang/issues/543) + covers numeric type literal naming. +- Issue + [#750: Naming conventions for Carbon-provided features](https://github.com/carbon-language/carbon-lang/issues/750) + was used for initial naming convention discussion. + +Related proposals: + +- Proposal + [#720: Property naming in C++](https://github.com/carbon-language/carbon-lang/pull/720) + covers nuances of property naming. + +## Proposal + +Only `UpperCamelCase` and `lower_snake_case` conventions will be used, in order +to minimize the variation in rules. + +- For idiomatic Carbon code: + - `UpperCamelCase` will be used when the named entity cannot have a + dynamically varying value. For example, functions, namespaces, or + compile-time constant values. + - `lower_snake_case` will be used when the named entity's value won't be + known until runtime, such as for variables. +- For Carbon-provided features: + - Keywords and type literals will use `lower_snake_case`. + - Other code will use the guidelines for idiomatic Carbon code. + +In other words: + +| Item | Convention | Explanation | +| ------------------------- | ------------------ | ------------------------------------------------------------------------------------------ | +| Packages | `UpperCamelCase` | Used for compile-time lookup. | +| Types | `UpperCamelCase` | Resolved at compile-time. | +| Functions | `UpperCamelCase` | Resolved at compile-time. | +| Methods | `UpperCamelCase` | Methods, including virtual methods, are equivalent to functions. | +| Generic parameters | `UpperCamelCase` | May vary based on inputs, but are ultimately resolved at compile-time. | +| Compile-time constants | `UpperCamelCase` | Resolved at compile-time. See [constants](#constants) for more remarks. | +| Variables | `lower_snake_case` | May be reassigned and thus require runtime information. | +| Member variables | `lower_snake_case` | Behave like variables. | +| Keywords | `lower_snake_case` | Special, and developers can be expected to be comfortable with this casing cross-language. | +| Type literals | `lower_snake_case` | Equivalent to keywords. | +| Boolean type and literals | `lower_snake_case` | Equivalent to keywords. | +| Other Carbon types | `UpperCamelCase` | Behave like normal types. | +| `Self` and `Base` | `UpperCamelCase` | These are similar to type members on a class. | + +## Details + +### Constants + +Supposing `let` might be used to designate a constant, consider the following +code: + +```carbon +package Example; + +let CompileTimeConstant: i32 = 7; + +fn RuntimeFunction(runtime_constant: i32); +``` + +In this example, `CompileTimeConstant` has a singular value (`7`) which is known +at compile-time. As such, it uses `UpperCamelCase`. + +On the other hand, `runtime_constant` may be constant within the function body, +but it is assigned at runtime when `RuntimeFunction` is called. Its value is +only known in a given runtime invocation of `RuntimeFunction`. As such, it uses +`lower_snake_case`. + +### Carbon-provided item naming + +Carbon-provided items are split into a few categories: + +- Keywords; for example, `for`, `fn`, and `var` +- Type literals; for example, `i`, `u`, and `f` +- Boolean type and literals; for example, `bool`, `true`, and `false` + - The separate categorization of booleans should not be taken as a rule + that only booleans would use lowercase; it's just the only example right + now. +- `Self` and `Base` +- Other Carbon types; for example, `Int`, `UInt`, and `String` + +Note that while other Carbon types currently use `UpperCamelCase`, that should +not be inferred to mean that future Carbon types will do the same. The leads +will make decisions on future naming. + +## Open questions + +## Rationale based on Carbon's goals + +- [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write) + - The intent is that limiting to `UpperCamelCase` and `lower_snake_case` + will offer developers a limited number of style rules to learn. + - There is a desire to maintain good ergonomics for developers. +- [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code) + - There is a general desire to maintain naming consistency with C++, and + this can be seen with keywords such as `for` as well as booleans. + +## Alternatives considered + +### Other naming conventions + +A couple naming conventions that were discussed briefly are: + +- `lowerCamelCase` names came up, but are hard to distinguish from + `lower_snake_case` for single-word identifiers. By contrast, + `UpperCamelCase` and `lower_snake_case` are distinct, whether a single word + or multiple. +- `ALL_CAPS_SNAKE_CASE` is used in C++ code, such as for macros and + compile-time constants. With Carbon, we hope the language is simple enough + that the readability benefit of an additional naming convention wouldn't + outweigh the cost of giving developers more naming conventions to learn. + +### Other conventions for naming Carbon types + +In detail, individual naming decisions that had alternative patterns or options +discussed were: + +- Type literals use `lower_snake_case` as described in issue + [#543: pick names for fixed-size integer types](https://github.com/carbon-language/carbon-lang/issues/543). + - `i8` is more ergonomic than `Int8` for brevity. + - `i32` and `i64` maintain the same length as C++'s `int`. + - We don't want to use `I32` because `I32` can be hard to visually + distinguish with `132` or `l32`, even though it may help screen readers. +- Booleans use `bool`, `true`, and `false` mainly because there's a desire not + to skew from C++. + - While leads are okay with some things being shadowed, such as `Self` and + `Base`, there is a desire not to allow shadowing of booleans. +- `Self` and `Base` are `UpperCamelCase` because leads want them to look more + like normal types. + - They may be implemented as a hybrid approach, using something similar to + lookup in classes so they aren't quite keywords, but somewhat similar to + keywords because leads may want to reject them as identifiers in + non-class contexts. +- `String` and potentially other names follow idiomatic naming conventions. + - Note that, in this case, divergence from C++ is accepted. + +Taking that into consideration, and that we are likely to keep +`lower_snake_case` for keywords and type literals in particular, a couple +options discussed would have mainly affect `self`, `base`, and `string`: + +- Anything language-provided without needing an `import` is always + `lower_snake_case`. + - `i32`, `bool`, `true`, `self`, `base`, `string.is_empty()` +- As above, but prelude class members follow standard naming conventions. + - `i32`, `bool`, `true`, `self`, `base`, `string.IsEmpty()` + +The understanding is that the difference between `bool` being treated similarly +to a keyword and `Self` being treated similarly to a type (both regardless of +implementation) is somewhat arbitrary. The decision not to use +`lower_snake_case` consistently depends mainly on the leaning of the leads, that +`self` and `base` felt like they shouldn't strictly be treated as keywords, and +`string` felt like the point where users should expect something more like an +idiomatic class. Future borderline cases may need to be decided by leads whether +they should be treated as more keyword-like or type-like.