Type Annotations
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; }
Pyro doesn't (currently) do anything with these type annotations, apart from verifying their syntax. The language is dynamically typed and is intended to remain so, but you can use type annotations to document your code's intended interface.1
Builtin Types
Annotations for builtin types are as follows:
-
any
-
bool
-
buf
-
char
-
err
-
err[type1, type2, ...]
-
f64
-
file
-
i64
-
iter
-
iter[type]
-
map
-
map[key_type, value_type]
-
null
-
queue
-
queue[type]
-
set
-
set[type]
-
stack
-
stack[type]
-
str
-
tup
-
tup[type1, type2, ...]
-
vec
-
vec[type]
The annotations below describe interfaces rather than specific types:
-
func
-
func(type1, type2, ...) -> type
-
iterable
-
iterable[type]
-
iterator
-
iterator[type]
A func
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:
var name: type; var name: type = value;
The same syntax works for function and method parameters:
def func_name(arg1: type, arg2: type) { ... }
Functions and methods can declare their return type by following their parameter list with an arrow, ->
, and a type declaration:
def func_name() -> type { ... }
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];
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];
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 either ani64
ornull
. -
bar
is avec
whose entries are eitherstr
ornull
. -
baz
is either amap
withstr
keys andi64
values ornull
.
Callable Values
You can indicate that a value is callable — i.e. that the value is a function, method, or class object — using the func
type, e.g.
var foo: func;
You can optionally specify the callable's return type, e.g.
var foo: func -> bool;
You can optionally specify the callable's parameter types, e.g.
var foo: func(); var bar: func() -> bool; var baz: func(i64, str); var bam: func(i64, str) -> bool;
-
foo
is a callable that takes no parameters. -
bar
is a callable that takes no parameters and returns abool
. -
baz
is a callable that takesi64
andstr
parameters. -
bam
is a callable that takesi64
andstr
parameters and returns abool
.
The func
type is nullable, e.g.
var foo: func?; var bar: func?(i64) -> bool;
-
foo
is either a callable ornull
. -
bar
is either a callable that takes takes ani64
parameter and returns abool
ornull
.
Type Names
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 UserType
. Type names can include a module path, e.g.
var bar: mod1::mod2::UserType;
Here, bar
is an instance of the class UserType
defined in the module mod1::mod2
.
Notes
- 1
-
Future versions of Pyro may offer optional type checking or automatic documentation generation using declared variable types. Currently, the compiler simply verifies that type declarations are syntactically correct, then discards them.