Data - Types and Kinds
Mech supports various primitive data types, each associated with one or more kinds. For example, the number 42 can be represented by an i32 datatype, which is of kind i32, signed, integer, real, number, and value (the latter of which is a sort of superset of all kinds).
Data types can be combined to form more complex structures, such as matrices, maps, sets, tuples, records, and tables. Each of these structures can also have associated kinds that are derived from the kinds of their constituent elements.
Data Types
Data in Mech is represented using one of the following primitive data types:
Data Type | Description |
|---|---|
Represents numeric values. | |
Represents text values. | |
Represents logical values | |
Represents symbolic constants. | |
Represents types or categories of values. | |
Represents an empty value or placeholder. |
Number
Represents numeric values, including integers, floating-point numbers, and complex numbers. Numbers can be further classified into a tree of subtypes, which affect which operations are valid on them:
Integers - Whole numbers, which can be positive, negative, or zero
Signed - Can represent both negative and positive values
i8- 8-bit signed integeri16- 16-bit signed integeri32- 32-bit signed integeri64- 64-bit signed integeri128- 128-bit signed integerUnsigned - Can only represent zero and positive values
Fractional - Decimal numbers with fractional components
Rational - Numbers represented as fractions of integers
r64- 64-bit rational numberComplex - Numbers with real and imaginary components
c64- 64-bit complex number
For more, see number.
String
A sequence of UTF-8 characters representing text.
Kind
<string>For more, see string.
Boolean
Represents logical truth values.
Kind
<bool>For more, see bool.
Atom
A symbolic constant, often used for tags or enums.
Kind
The kind of an atom is itself. For example, the atom :A has the kind:
<:A>For more, see atom.
Kind
Represents a type or category of values, such as i32, f64, string, etc. Kinds can be used to classify values and determine their operations.
Kind
The kind of a kind is itself, and kind. For example, the kind <i32> has the kind:
<<i32>><kind>
for more, see kind.
Empty
Represents an empty value, placeholder, or the absence of a value.
Kind
<_>Examples
x:=_--An empty value
y<_>:=_--An empty value of kind
_
For more, see empty.
Data Structures
Data structures in Mech are used to organize and manipulate collections of data. The primary data structures include:
Data Structure | Description |
|---|---|
stores key-value pairs for fast lookups. | |
2D array of homogenous values arranged in rows and columns. | |
groups related fields, usually for representing structured data. | |
unordered collection of unique values | |
collection of heterogeneous data organized into rows and columns. | |
fixed-size, ordered grouping of heterogeneous values. |
Kinds
Every value in Mech has one or more associated kinds, which describe its type and properties.
Syntax
Any valid identifier can be used as a kind as long as it is unique in the program. Mech provides a set of predefined kinds for common data types, but you can also define your own kinds as well, and construct compound kinds from other kinds.
For example, the kind of a signed 32-bit integer is represented as: <i32>. The kind of a matrix is represented as <[T]>. These can be combined into the kind <[i32]>, which represents a matrix of signed 32-bit integers.
Kind Annotations
Kind annotations are a tag that you can apply to values and expressions to specify their type explicitly. Syntatically they are specified with a form called a "kirby", which encases the kind in angle brackets:
<u8>--An unsigned 8-bit integer
<[u8]>--A matrix of unsigned 8-bit integers
<(o,O)>--A tuple of two elements of kind
oandOrespectively
Kind annotations can be used to annotate literals with their data type:
x:=42<u8>-- defines x as an unsigned 8-bit integer with the value 42
They can be used for type conversions as well:
x:=[123]--1x3 row vec of f64 numbers:
y<[u8]>:=[[f64]:1,3456]--1x3 row vec of u8 numbers:
z<[u8]>:=x--[u8]:1,3Convert
[f64]:1,3to[u8]:1,3
Kind annotations can also be assigned to variables:
x:=<u8>-- Assigns the kind u8 as the value of x
The kind of x is <<u8>>.
Simple Kinds
Kinds start from one of the primitive data types:
Data Type | Kind |
|---|---|
Signed integers | <i8>, <i16>, <i32>, <i64>, <i128> |
Unsigned integers | <u8>, <u16>, <u32>, <u64>, <u128> |
Floating-point | <f32>, <f64> |
Rational | <r64> |
Complex | <c64> |
String | <string> |
Boolean | <bool> |
Atom | <:atom> |
Kind | <<kind>> |
Empty | <_> |
Compound Kinds
Kinds compose into more complex kinds based on the data structures they represent.
Data Structure | Kind | Example | Meaning |
|---|---|---|---|
Matrix |
| <[u8]:2,3> | 2x3 matrix of |
Set |
| <{u8}:3> | Set of 3 |
Record |
| <{x<u8>,y<string>}> | Record with fields |
Map |
| <{string:i32}> | Map from |
Table |
| <|x<u8>,y<string>|:3> | Table with columns |
Tuple |
| <(u8,string,bool)> | Tuple of |
Custom Kinds
You can define a custom kind with the following syntax:
<T>:=<S>-- Defines custom kind T, an alias for S
For example, if you wanted to represent a 3D point as a vector of three f32 values, you could define a custom kind like this:
<point3>:=<[f32]:3>Then you could use this kind to define a variable:
v1<point3>:=[123]--Defines v1, a 3-element vector of f32 values
v2<point3>:=[45]--Error: kind mismatch, expected 3 elements but got 2
Enumerations
Enumerations, also known as enums, are a special kind that defines variants with optional associated data. Enums are useful for representing a fixed set of related values.
You can define an enum kind like this:
<color>:=red|green|blueThe kind of the enum is <color>, and the possible values are the variants :color/red, :color/green, and :color/blue.
d<color>:=:color/yellow-- Error: yellow is not a variant