Type Annotations
- Builtin Types
- Syntax
- Nullable Types
- Callable Values
- User-Defined Types
- Type Aliases
- Variadic Functions
Pyro supports optional type annotations for variable, function, and method declarations, e.g.
var foo: i64 = 123; var bar: f64 = 1.0; def is_long(text: str) -> bool { return text:byte_count() > 100; } def increment(value: i64, inc: i64 = 1) -> i64 { return value + inc; }
Pyro doesn't (currently) do anything with these type annotations, apart from verifying their syntax, but they're useful for documenting your code.
Future versions of Pyro may support optional type-checking or automatic documentation-generation using type annotations.
Builtin Types
Annotations for builtin types are as follows:
-
any
-
bool
-
buf
-
class
-
enum
-
err
-
f64
-
file
-
func
-
i64
-
instance
-
iter
-
iter[type]
-
map
-
map[key_type, value_type]
-
method
-
module
-
null
-
queue
-
queue[type]
-
rune
-
set
-
set[type]
-
stack
-
stack[type]
-
str
-
tup
-
tup[type1, type2, ...]
-
vec
-
vec[type]
The annotations below describe interfaces rather than concrete types:
-
callable
-
callable(type1, type2, ...) -> type
-
iterable
-
iterable[type]
-
iterator
-
iterator[type]
A callable
value is callable;
an iterable
value has an :$iter()
method that returns an iterator;
an iterator
value has a :$next()
method that returns the next item from a sequence.
Type annotations beginning with a lowercase letter are reserved for language builtins.
Syntax
Specify a variable's type by following its name with a colon and a type declaration, e.g.
var foo: i64; var bar: f64 = 1.0;
If you don't specify a variable's type, its implicit type is any
.
The same syntax works for function and method parameters, e.g.
def func(arg1: i64, arg2: f64 = 1.0) { ... }
If you don't specify a parameter's type, its implicit type is any
.
Functions and methods can declare their return type by following their parameter list with an arrow, ->
, and a type declaration, e.g.
def func() -> str { ... }
If you don't specify a return type, the implicit return type is any
.
Builtin container types can optionally specify their content types in square brackets, e.g.
var foo: vec[str]; var bar: map[str, i64]; var baz: tup[i64, bool, str];
-
foo
is a vector containingstr
values. -
bar
is a map containingstr
keys andi64
values. -
baz
is a tuple containing three entries — in order, ani64
, abool
, and astr
.
If you don't specify a container's content types, their implicit type is any
, e.g.
var foo: vec; var bar: map; var baz: tup;
-
foo
is a vector containingany
values. -
bar
is a map containingany
keys andany
values. -
baz
is a tuple containing an unspecified number ofany
values.
Where a type can be one of a discrete set of options, separate the options with a |
, e.g.
var foo: i64|f64; var bar: map[str, i64|f64];
-
foo
is either ani64
or anf64
. -
bar
is a map containingstr
keys and values which, individually, may be eitheri64
orf64
.
Type declarations can be nested as required, e.g.
var foo: vec[map[str, i64|f64]];
Nullable Types
You can indicate that a type is nullable — i.e. can be either the specified type or null
— by appending a ?
to the type name, e.g.
var foo: i64?; var bar: vec[str?]; var baz: map?[str, i64];
-
foo
is eithernull
or ani64
. -
bar
is avec
whose entries are eithernull
orstr
. -
baz
is eithernull
or amap
withstr
keys andi64
values.
This is simply a shortcut for declaring the type as type|null
.
Callable Values
You can indicate that a value is callable — i.e. that the value is a function, method, class, or callable instance — using the callable
type, e.g.
var foo: callable;
You can optionally specify the callable's return type, e.g.
var foo: callable -> bool;
If you don't specify a return type, the implicit return type is any
.
You can optionally specify the callable's parameter types, e.g.
var foo: callable(); var bar: callable() -> bool; var baz: callable(i64, str); var bam: callable(i64, str) -> bool;
-
foo
is a callable that takes no parameters and returnsany
. -
bar
is a callable that takes no parameters and returns abool
. -
baz
is a callable that takes two paramters, ani64
and astr
, and returnsany
. -
bam
is a callable that takes two paramters, ani64
and astr
, and returns abool
.
The callable
type is nullable, e.g.
var foo: callable?; var bar: callable?(i64) -> bool;
-
foo
is eithernull
or a callable. -
bar
is eithernull
or a callable that takes takes ani64
parameter and returns abool
.
User-Defined Types
A type name should specify either one of the builtin types or a user-defined type, possibly imported from a module, e.g.
var foo: UserType;
Here, foo
is an instance of the class or member of the enum UserType
. Type names can include a module path, e.g.
var bar: mod1::mod2::UserType;
Here, bar
is an instance of the class or member of the enum UserType
defined in the module mod1::mod2
.
Type Aliases
You can define an alias for a type using a typedef
statement, e.g.
typedef Token tup[str, i64, bool]; def makes_token() -> Token { return $tup("FOO", 123, true); }
Variadic Functions
A type annotation in a variadic function specifies the type of the individual parameter values, e.g.
def add(*args: i64|f64) { return args:iter():sum(); } assert add(1, 2.0) == 3.0;
Here, add()
is a function that takes a variable number of arguments; each argument can be an i64
or an f64
.