Table

Syntax

Basic Syntax

Inline Syntax

Fancy Syntax

Kind

Construction

From vectors

From a matrix

From records

Accessing Elements

Access a Column

Access an Element

Access a Record

Access Several Records

Filter Records

Heterogeneous Columns

Partial Columns

Table

A table is a set of records, where each record corresponds to a row and each column has a name and kind. Tables provide structured, columnar data that is flexible and human-readable.

Syntax

Basic Syntax

Tables are defined using the pipe | character. Each column is defined with a name and a kind, which describes the type of data it holds.

| x<f32>  y<bool> | 
|  1.2     true   |
|  1.3     false  |

This creates a table with two columns, x of kind f32 and y of kind bool:

x<f32>
y<bool>
1.2 true
1.3 false

Inline Syntax

You can write tables inline as well:

| x<f32>  y<bool> | 1.2 true | 1.3 false |

Fancy Syntax

The Mech REPL formats matrix output using fancy box drawing characters for better readability.

╭────────┬─────────╮
│ x<f32> │ y<bool> │
├────────┼─────────┤
│  1.2   │  true   │
│  1.3   │  false  │
╰────────┴─────────╯

Mech can parse data formatted this way, allowing you to copy or pipe REPL output directly into a Mech program that expects a table. The above example evaluates to:

x<u64>
y<bool>
1.2 true
1.3 false

Fancy tables can be formatted in a variety of ways:

╭────────┬────────╮
│ x<u64> │ y<f32> │
├────────┼────────┤
│   1    │   2    │
├────────┼────────┤
│   3    │   4    │
╰────────┴────────╯

This one has no horizontal lines between rows, making it more compact:

╭────────┬────────╮
│ x<u64> │ y<f32> │
│   1    │   2    │
│   3    │   4    │
╰────────┴────────╯

Kind

A table's kind describes the names and kinds of the columns, as well as the number of rows in the table. For example:

<|x<u8>,y<f32>|:3>

This represents a table with two columns, x of kind u8 and y of kind f32, and 3 rows.

Construction

Tables can be constructed of vectors, matrices, or records.

From vectors

From a matrix

You can create a table from a matrix using a kind annotation, as long as the kinds of the table columns are compatible with the matrix kind. For example, if you have a matrix of kind f64, you can create a table with columns of kind f64:

For example:

x:=[
1 3
2 4
]
a<|foo<f64>,bar<f64>|>:=x

This creates a table a with two columns, foo and bar, both of kind f64, and two rows corresponding to the rows of the matrix x.

The matrix [a.foo a.bar] is identical to the original matrix x.

It's possible to convert a matrix of one kind to a table of different kinded columns, as long as the conversion is valid. For example, you can convert a matrix of f64 to a table with u8 columns:

b<|foo<u8>,bar<i8>|>:=x

From records

Accessing Elements

Consider the table:

a:=
x<f64>
y<bool>
1.6 true
1.3 false
2.7 false
1.5 true

Access a Column

Use dot indexing to access columns. For example a.x. The kind of the result is a column vector with elements of the column's kind. For instance, column x has kind f32, so the result of accessing that column is a column vector of kind [f32], with the same number of rows as the table:

a.x--

Select column x, which has kind [f32]

Access an Element

You can access an individual element in a table column by specifying the row index on the selected column:

a.x[1]--

Select the first element of column x, which has kind f32

Table columns are just vectors, so they support the same indexing operations as vectors.

Access a Record

You can access a record in a table by specifying the row index on the table itself:

a{1}--

Select the first record in the table, returns a record

Access Several Records

You can access a range of records by using a vector as an index:

a{2..=3}--

Select records 2 through 3, returns a table

It's possible to select the same row multiple times:

a{[
1
1
2
2
]
}
--

Select records 1 and 2 twice

Filter Records

You can filter records using logical indexing. For example, to select records where y is true:

a{a.y}--

Select records where y is true

Or to filter records where x is greater than 1.5:

a{a.x>1.5}--

Select records where x is greater than 1.5

Heterogeneous Columns

The kind * indicates that a column may contain heterogeneous data:

x<*>
y<*>
1.2 true
"Hi" 8

Each cell in the column may hold a different type of value.

Partial Columns

You can omit values in the table using using _ to indicate a missing value. In this case, the kind of the column must be annotated with an option kind, indicated by a ? suffix:

x<u8?>
y<string?>
z<[u8]:1,3?>
_ "a" [
1
2
3
]
4 "b" _
7 _ [
7
8
9
]