Functions
Functions in Teal should work like you expect, and we have already showed various examples.
You can declare nominal function types, like we do for records, to avoid
longwinded type declarations, especially when declaring functions that take
callbacks. This is done with using function
types, and they can be generic as
well:
local type Comparator = function<T>(T, T): boolean
local function mysort<A>(arr: {A}, cmp?: Comparator<A>)
-- ...
end
Note that functions can have optional arguments, as in the cmp?
example above.
This only affects the arity of the functions (that is, the number of arguments
passed to a function), not their types. Note that the question mark is assigned
to the argument name, not its type. If an argument is not optional, it may still
be given explicitly as nil
.
Another thing to know about function declarations is that you can parenthesize the declaration of return types, to avoid ambiguities when using nested declarations and multiple returns:
f: function(function(? string):(number, number), number)
Note also that in this example the string argument of the return function type is optional. When declaring optional arguments in function type declarations which do not use argument names, The question mark is placed ahead of the type. Again, this is an attribute of the argument position, not of the argument type itself.
You can declare functions that generate iterators which can be used in
for
statements: the function needs to produce another function that iterates.
This is an example taken the book "Programming in Lua":
local function allwords(): (function(): string)
local line = io.read()
local pos = 1
return function(): string
while line do
local s, e = line:find("%w+", pos)
if s then
pos = e + 1
return line:sub(s, e)
else
line = io.read()
pos = 1
end
end
return nil
end
end
for word in allwords() do
print(word)
end
The only changes made to the code above were the addition of type signatures in both function declarations.
Teal also supports macro expressions, which are a restricted form of function whose contents are expanded inline when generating Lua code.
Variadic functions
Just like in Lua, some functions in Teal may receive a variable amount of
arguments. Variadic functions can be declared by specifying ...
as the last
argument of the function:
local function test(...: number)
print(...)
end
test(1, 2, 3)
In case your function returns a variable amount of values, you may also declare
variadic return types by using the type...
syntax:
local function test(...: number): number...
return ...
end
local a, b, c = test(1, 2, 3)
If your function is very dynamic by nature (for example, you are typing a
Lua function that can return anything), a typical return type will be any...
.
When using these functions, often one knows at the call site what are the
types of the expected returns, given the arguments that were passed. To set
the types of these dynamic returns, you can use the as
operator over
multiple values, using a parenthesized list of types:
local s = { 1234, "ola" }
local a, b = table.unpack(s) as (number, string)
print(a + 1) -- `a` has type number
print(b:upper()) -- `b` has type string