We begin with literals and variables, two basic building blocks for any expression. Along the way, additional concepts will be introduced, such as types, permissions, variable declarations, assignment, and scope.


A literal is a specific, unchangeable value. Each of these numbers is a literal:

1e6          // 1000000.0
-1_000_000   // underscores are ignored
0x1000       // Hexadecimal

Beyond numbers, other forms of literals will be introduced later, including:

Named constants

Constant literals can be given a name. For example:

const pi = 3.141592

With this declaration in place, any program reference to the name pi will substitute in the the corresponding floating-point constant literal value.


Every value has a type it belongs to. A type is a pattern that:

Every value in a program has a type, known at compile-time due to an explicit declaration or because the type can be easily inferred based on the context. By knowing the types of all values, the compiler can optimize a program's performance and memory use. Clear typing facilitates precise, flexible data manipulation and improves the safe and correct use of data.

The names of specific types are capitalized by convention. This helps cleanly distinguish variable names from type names, reducing unexpected naming conflicts and improving code clarity. One notable exception to this naming convention is the type names for the primitive numeric types.

Number types

For the next few pages, examples will only use the built-in number types, which specify their bit-size as part of the type's name. Here they are:

Later, a number of other types will be introduced.

Typed Number Literals

To explicitly specify the type for a numeric literal, append the type name right after the number:

65u8       // 8-bit unsigned integer
1f64       // 64-bit floating point number

If the type is omitted, the number is understood to be 32-bits. When the number explicitly includes a decimal point or exponent, it is treated as a floating point number (f32). Otherwise, it is considered to be a signed integer (i32).

3.14159    // f32 (because of the decimal point)
1e6        // f32 (because of the exponent)
1_000_000  // i32 (no decimal point or exponent)

Type name shortcuts are also supported:

1000u      // u32
1f         // f32
1d         // f64


A variable is like a named container which holds a value of some specific type.

Variable declarations

Before a variable can be used, it must first be declared and initialized. This example explicitly does both:

imm height f32 = 1.86

Let's examine each part of this variable declaration statement:

When an initial value is specified, the type can usually be omitted. It will be inferred, as this example shows:

imm height = 1.86     // f32 type is inferred
imm width  = height   // its value is 1.86 and type is f32

Notice that the second statement makes use of the variable 'height' after it has been declared and initialized.

Delayed initialization

It is often preferable to initialize a variable as part of declaration. When that is not realistic, initialization may be performed later using an assignment:

imm height f32
// ... some statements here ...
height = 1.86         // Initialize height now

An assignment essentially copies the evaluated value of the expression to the right of the = into the variable specified to the left. (Later, we will show that assignment can also be used to place values into structures that lie "within" a variable's value.) Any assignment is itself an expression, and may be used wherever expressions are allowed.

It is worth pointing out that any attempt to re-assign 'height' later to another value will trigger an error message:

height = 2.12         // **ERROR** since height is immutable and initialized

Mutable Variables

What if we need to change a variable's value after initialization? To allow that, use mut (instead of imm) on the declaration statement:

mut age = 23      // type is i32
// ... some statements here ...
age = 24          // alters age to hold 24 instead

mut and imm are called permissions. Cone supports a number of other permissions. These are discussed more fully on the Permissions page.

Note: If we had tried to re-assign age to 24.0, we would have gotten an error message. This is because age is declared to only hold integer values, and 24.0 is a floating point number. Type safety of variables requires that the expression's type be the same or coerceable.

Scope and Visibility

As we have seen, variables have a name, permission, type and value. They also have a scope and visibility. Scope and visibility restrict where a variable may be referenced and used in a program.