# 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.