Skip to content

Types

This page describes different data types in Pen.

It represents a real number. It is implemented as a 64-bit floating point number of IEEE 754.

number
3.14
-42

It is a boolean value of true or false.

boolean
true
false

It represents a missing value. It has only a single value of none.

none
none

It is a byte array.

string

String literals are sequences of bytes. They are often used to represent texts encoded in UTF-8.

"foo"

String literals can contain the following escape sequences.

Escape sequence Name
\n New line
\r Carriage return
\t Tab
\" Double quote
\\ Backslash
\x9f Byte

A function represents reusable computation with arguments and a result.

Functions represent not only pure computation but may also execute side effects, such as I/O.

\(number, number) number
\(x number, y number) number {
x + y
}

It is a list of values. Its type contains an element type between [ and ].

[number]

A list literal contains its element type and elements as expressions.

[number]
[number 1]
[number 1, 2, 3]

You can create new lists from existing ones by spreading elements of the old ones prefixed by ... into the new ones.

[number x, ...xs]

Note that expressions within list literals are evaluated lazily; they are evaluated only if their values are required.

It is a map from keys to values. Its type contains key and value types between { and } separated by :.

{string: number}

A map literal contains its key and value types and key-value pairs as expressions.

{string: number}
{string: number "foo": 1}
{string: number "foo": 1, "bar": 2}

You can create new maps from existing ones by spreading entries of the old ones prefixed by ... into the new ones.

{string: number ...map, "foo": 1}

It combines multiple types into a single type. Each field of a record type is composed of its name and type.

Fields are not accessible outside modules where they are defined by default.

type person {
name string
age number
}

To expose fields as well as the type itself to other modules, you need to capitalize their names.

type Person {
Name string
Age number
}

Record values are constructed using record literals containing their field names and values separated by commas.

person{name: "foo", age: 42}

You can also create new records from existing ones spreading fields of the old ones into the new ones.

person{...one, name: "bar"}

You can access field values by appending their names with . prefixes to expressions of record types.

john.name

It is a union of multiple types.

For example, the type below represents values that can be either number or none.

number | none

Literally, it’s an any type. Any values can be converted to the type.

any

It is an error. You can create error values by calling the error built-in function. See also Error handling.

error