Naming conventions

Pull request

Table of contents

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:

Carbon artifacts

Related issues:

Related proposals:

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 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:

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

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