We've talked about types before, mostly in regard to the integer and floating point number types (e.g., i32 or f32). Cone offers a rich, versatile collection of types, whose documentation extends across quite a few chapters.
What is a type? Broadly speaking, it is a pattern that:
- Establishes what kind of data a value of that type carries.
- Determines how values are digitally encoded in memory.
- Specifies the methods (functions) that can be performed with values of that type
- Enforces constraints to ensure the type's values are handled consistently and safely.
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 separate the global namespace between value types and variables, reducing unexpected naming conflicts and improving code clarity. One notable exception to this naming convention is the type names for the primitive numeric types.
This page provides a helpful overview of Cone's diverse range of types. These enable definition of custom types as needed by a program or library.
The concrete types are used to instantiate specific data values:
- Built-in number types. This includes the signed and unsigned integers and floating point numbers. It also includes bool (a 1-bit unsigned integer) and char (a 32-bit unsigned integer) large enough to hold a unicode value. These are the atomic building blocks on which (nearly) all other types rest. Their bit sizes are designed to exploit the byte and word alignments used by most CPUs.
- Field-based structure types. struct defines a named type that describes a group of values, called fields, each with its own type and name. A number of other special-purpose types are field-based, such as range, closure, trait, interface, allocator, and run-time permission. Although traits never directly instantiate values, they can be used to help assemble struct types which do.
- Indexed collection types. These types hold a collection of values that all have the same type. Some collection types index access to its values using an unsigned integer (e.g., a List or a Text string). Other collection types index its values using a hashed value (typically a Text).
- Variant types. These types enable a single value to be one of several types. The value's specific type is only known (and changeable) at runtime. Variant type capability includes sum and nullable types as well as tagged structs. Special language features, like pattern matching, are used to ensure safe use of variant-typed data.
System Resource Types
These types facilitate low-level, safe use of memory, functions and threads.
- Reference types. Reference types provide a memory- and race-safe way for a program to create one or more managed paths used to indirectly access a single value. References can point to concrete types, another reference, functions, collection slice, or an interface- or trait-subtyped struct. All references are assigned a permission (see below). References are either borrowed for a lexically-constrained lifetime or managed by a specified allocator.
- Permission types. Permission types are used to constrain the mutability and aliasing of values held by variables or pointed to by references. Use of permissions prevents race conditions. Some permission types are dynamic, using runtime synchronization mechanisms to enforce constraints. Other permissions are static, and entirely enforced at compile-time.
- Allocator types. Allocator types manage the layout and lifetime of values in memory. Allocators support a broad range of safe memory management strategies, such as lexical single-owner, reference counted, tracing GC, pools and arenas.
- Pointer types. Pointer types are very similar to references in their fundamental capability. However, they are not constrained by permission and allocator safety mechanisms. Instead, they offer greater flexibility in terms of pointer arithmetic and type re-casting.
- Function types. This is the signature for a function (or method): its named parameter types and its return type (or type tuple).
- Thread types. Thread types support the structured spawning, management and convergence of multiple threads. Multiple thread strategies are supported, such as co-routines, native and green threads.
Using template metaprogramming, one can define a collection of types that share common logic, but whose implementation details vary according to the specific type parameters applied to the template. Most indexed collection types are implemented using templates. Thus, hash-indexed collections share a similar logic, but that logic varies according to the specified types of the hash and element values.