Types

This page describes different data types in Pen.

Number

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

number

Literals

3.14
-42

Boolean

It is a boolean value of true or false.

boolean

Literals

true
false

None

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

none

Literals

none

String

It is a byte array.

string

Literals

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

"foo"

Escape sequences

String literals can contain the following escape sequences.

Escape sequenceName
\nNew line
\rCarriage return
\tTab
\"Double quote
\\Backslash
\x9fByte

Functions

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

Literals

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

Lists

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

[number]

Literals

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.

Maps

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

{string: number}

Literals

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}

You can also delete a key from a map omitting its value.

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

Records

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
}

Literals

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

Unions

It is a union of multiple types.

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

number | none

Any

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

any

Error

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

error