Core types
Inko provides various core types, such as String, Int, and Array.
Some of these types are value types, which means that when they are moved a copy is created and then moved.
Array
Array is a contiguous growable array type and can store any value, as long as
all values in the array are of the same type.
Bool
Inko's boolean type is Bool. Instances of Bool are created using true and
false.
Bool is a value type.
ByteArray
ByteArray is similar to Array, except it's optimised for storing bytes. A
ByteArray needs less memory compared to an Array, but can only store Int
values in the range of 0 up to (and including) 255.
Float
The Float type is used for IEEE 754 double-precision floating point numbers.
Float is a value type.
Int
The Int type is used for integers. Integers are 64 bits signed integers.
Int is a value type.
Map
Map is a hash map and can store key-value pairs of any type, as long as the
keys implement the traits std.hash.Hash and std.cmp.Equal.
Nil
Nil is Inko's unit type, and used to signal the complete lack of a value. The
difference with Option is that a value of type Nil can only ever be Nil,
not something else. Nil is used as the default return type of methods, and in
some cases can be used to explicitly ignore the result of an expression (e.g. in
pattern matching bodies).
Nil is a value type.
Option
Option is an algebraic data type/enum used to represent an optional value. It
has two constructor: Some(T) and None, with None signalling the lack of a
value.
Result
Result is an algebraic data type/enum used for error handling. It has two
constructors: Ok(T) and Error(E). The Ok constructor signals the success
of an operation, while Error signals an error occurred.
String
The String type is used for strings. Strings are UTF-8 encoded immutable
strings. Internally strings are represented such that they can be efficiently
passed to C code, at the cost of one extra byte of overhead per string.
String uses atomic reference counting when copying. This means that ten copies
of a 1 GiB String only require 1 GiB of memory.
String is a value type.
Never
Never is a type that indicates something never happens. When used as a return
type, it means the method never returns. An example of this is
std.process.panic(): this method panics and thus returns a Never.
You'll likely never need to use this type directly.
The Never type can only be used as the return type of a method, and can't be
used as a generic type argument (e.g. Option[Never] is invalid).
Self
Self is not a type on its own but rather a sort of "placeholder" type. When
used inside a trait definition, it refers to the type that implements the
trait:
trait Example {
fn example -> ref Self {
self
}
}
type User {
let @name: String
}
impl Example for User {}
User(name: 'Alice').example # => ref User
Here calling User.example produces a value of ref User because Self is
replaced with the User type.
When Self is used inside a type definition it refers to the surrounding
type:
type User {
let @name: String
fn foo -> ref Self {
self
}
fn bar -> ref User {
self
}
}
Here the definitions for User.foo and User.bar are semantically equivalent,
as Self is replaced with User upon reference.
When using Self inside a generic type, you can't specify additional type
arguments, meaning this is invalid:
type List[T] {
fn example -> Self[Int] {
...
}
}
static methods can only use Self in the return type, not in their body or
arguments:
type List[T] {
fn static invalid(value: Self) {
...
}
}
Module methods can't use Self at all, meaning the following definitions are
invalid:
fn invalid1(value: Self) {
...
}
fn invalid2 -> Self {
...
}
fn invalid3 {
let variable: Self = ...
}