Identifiers

An identifier names a binding, function, type, field, module or other declaration.

Identifier ::= IdentStart IdentContinue*
IdentStart ::= 'A'…'Z' | 'a'…'z' | '_'
IdentContinue ::= IdentStart | '0'…'9'

An identifier starts with an ASCII letter or an underscore and continues with letters, digits and underscores. It cannot be one of the 38 keywords.

let count = 1;
let x1 = 2;
let _scratch = 3;
let parsedValue = 4;

Rules

  • ASCII only. Letters outside ASCII are not identifier characters: let café = 1; stops with error: unexpected character 'é' (U+00E9). Non-ASCII text belongs in literals and comments.
  • Case-sensitive. count, Count and COUNT are three different names.
  • No keywords. A keyword in a name's place is a syntax error, such as error: expected a pattern after the binding keyword before 'while' for let while = 1;. For none and fail the message names the problem directly: error: 'none' is a reserved keyword and cannot name a binding.
  • A lone _ is not a name. In a binding or pattern, _ discards the value instead of naming it: let _ = Compute();. See Destructuring.

Primitive type names such as int, bool and char8 are not keywords; they are predefined type names, listed in the Primitive Types appendix. A few other words have a meaning only in a particular position; Keywords lists them.

Naming conventions

Rux code uses two spellings, and rux lint checks them:

SpellingUsed forExamples
PascalCaseTypes (structs, enums, variants, unions, interfaces, aliases), enum and variant cases, functions and methods, constants, modulesHttpRequest, ParseInput, MaxSize, Io
camelCaseLocal bindings, parameters, loop variables, fields, named variant fieldsuserId, fileName, red

Neither spelling uses underscores. A name that breaks the convention compiles, and rux lint suggests the fix:

warning: function name 'parse_input' should be PascalCase
  help: rename it to 'ParseInput'
warning: local variable name 'Result' should be camelCase
  help: rename it to 'result'

The primitive types and their built-in aliases (int, float64, byte) are lower case by long tradition. A declaration that has to keep a foreign spelling — a C type name in a binding, say — can opt out with #Allow("naming.type") or #Allow("naming.const").

See also

  • Keywords — the words an identifier cannot be
  • Modules — qualified names such as Io::PrintLine
  • rux lint — the naming checks
  • Variable — the lesson on naming values