Defining functions
This page explains how to define functions within TypeDB schemas.
Understanding functions
Functions provide powerful abstractions of query logic, and a cornerstone of the functional database programming model. Functions calls can be nested, recursive, negated, and they natively embed into TypeQL’s declarative patterns.
Functions can be defined in a schema and later used in queries to:
-
Reduce code duplication by encapsulating common logic within functions.
-
Simplify complex TypeQL queries for improved readability and maintenance.
-
Share reusable query logic with other developers.
While this page focuses on defining functions in schemas, it is also possible to create temporary functions for one-time query execution. Refer to the TypeQL documentation for comprehensive information and additional usage examples.
Function definition queries
Similar to type definitions, functions can be stored in a database schema using schema
transactions.
Three types of schema definition queries are available for working with functions:
-
define <function declaration>
. Adefine
query adds a new function to the schema for future use. -
undefine fun <function name>
. Anundefine
query removes a function from the schema. -
redefine <function declaration>
. Aredefine
query updates an existing function in the schema.
Arithmetic functions
The simplest functions perform arithmetic operations. For example, the following query defines a function that accepts two integers and returns their sum. The function declaration has several key components:
-
The
fun
keyword, indicating the start of a function declaration. -
The function name.
-
A list of arguments, including their variable names and types.
-
The return type:
{}
denotes a stream function, as it can return multiple results. -
The function body, which contains a read pipeline and a
return
statement with valid TypeQL expressions.
define
fun add_streamed($x: integer, $y: integer) -> { integer }:
match
let $z = $x + $y;
return { $z };
If you are certain that $z
will only match a single value (or if only one value is needed), the first
or last
keywords can be used to ensure the function returns a single result.
define
fun add($x: integer, $y: integer) -> integer:
match
let $z = $x + $y;
return first $z;
Querying for types
Since TypeDB has a strong emphasis on types, functions can also return types.
For example, the following function retrieves all phone
attributes associated with a specific user
:
define
fun user_phones($user: user) -> { phone }:
match
$user has phone $phone;
return { $phone };
Functions within functions and tuple outputs
As described in the function syntax basics, return statements can include any valid TypeQL expressions. This allows functions to call other functions. Additionally, multiple expressions can be combined to return a tuple of results instead of a single scalar value.
For example, the following function uses two built-in aggregation function calls to produce a tuple result:
define
fun karma_sum_and_sum_squares() -> double, double:
match
$karma isa karma;
let $karma-squared = $karma * $karma;
return sum($karma), sum($karma-squared);
The output type here is not a stream because each tuple component is derived from an aggregation, which produces a single result. |
Refer to Using functions for more details on calling functions.
Function undefinition
To undefine a function from a schema, you only need its name, which uniquely identifies it. The following query removes a function defined earlier:
undefine
fun add_streamed;
Function redefinition
To redefine an existing function, use the same define
syntax with the redefine
keyword.
The query below updates a previously defined function to accept a username
instead of a specific user
:
redefine
fun user_phones($username-value: string) -> { phone }:
match
$user isa user, has username $username, has phone $phone;
$username == $username-value;
return { $phone };
You can only redefine existing functions. The function name must remain the same. To change the name, define a new function and undefine the old one. |
Using functions
Functions can be called in queries as other statements. As shown in previous examples, to call a function, reference its name and pass the required arguments (if applicable) within parentheses.
For functions returning a single result, use a simple assignment to bind the output variable to the function’s result:
match
let $answer = add(2016, 9);
The |
For functions returning a stream, use let … in
statements to bind variables:
match
$user isa user;
let $phone in user_phones($user);
Practice Task
How would you call this function after redefining it?
Answer
user_phones("Bob")
To handle tuple results, bind the appropriate number of variables to unpack the function’s output:
match
let $karma, $karma-squared in karma_sum_and_sum_squares();
For further details, refer to the TypeQL documentation.