-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- For idiomatic Carbon code: - `UpperCamelCase` will be used when the identifier can be resolved to a specific value at compile-time. - `lower_snake_case` will be used when the identifier'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. Co-authored-by: Chandler Carruth <chandlerc@gmail.com> Co-authored-by: Richard Smith <richard@metafoo.co.uk> Co-authored-by: josh11b <josh11b@users.noreply.github.com>
- Loading branch information
1 parent
6218aff
commit 086834d
Showing
1 changed file
with
216 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
# Naming conventions | ||
|
||
<!-- | ||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM | ||
Exceptions. See /LICENSE for license information. | ||
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
--> | ||
|
||
[Pull request](https://github.com/carbon-language/carbon-lang/pull/861) | ||
|
||
<!-- toc --> | ||
|
||
## 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) | ||
|
||
<!-- tocstop --> | ||
|
||
## 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<digits>`, `u<digits>`, and `f<digits>` | ||
- 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. |