Writing functions
Syntax
Declaring a function
Functions in TypeQL are declared using the keyword fun
.
A function declaration consists of:
-
A function signature which itself consists of:
-
A function name.
-
Typed input arguments (optional).
-
A return type.
-
-
A read pipeline as the function body.
-
A return statement that produces results of the specified return type.
fun <function-name> ( <optional-arguments> ) -> <return-types>:
<read_pipeline>
return <return-statement>
-
<function-name>
is a valid label (i.e. a not reserved keyword or a TypeQL literal). -
<optional-arguments>
is a list of zero of more typed variables, written in the format$a : A, $b : B, …
-
<return-types>
consists of at least one<return-type>
and can be:The types
A, B, …
above can be either user-defined types (e.g. an entity typeuser
) or primitive value types (e.g.boolean
). -
<read_pipeline>
includes any read pipeline. -
<return-statement>
may consist of variables, function calls, and built-in reductions:-
Scalar return statements are of the form
$a;
. -
Tuple return statements are of the form
$a, $b, <built-in-reduction>, scalar_fun($c), …;
(see reduce for available built-in reductions). -
Stream return statements are of the form
{ $a, $b, scalar_fun($c), … };
.
Positions matter! Returns of functions are assigned by position.
-
Calling a function
<function-name>(<arguments>)
<arguments>
to a function call are of the form $a, $b, …
. They are always variables (and not expressions).
Function can be called:
-
as part of an expression. For example:
Scalar expression comparison$x + 1 < f1($y) + f2($y);
Scalar expression assignmentlet $x = scalar_fun($a, $b) / 2; # f3 is
-
as part of a tuple or stream assignment, for example:
Tuple assignmentlet $x, $y = tuple_fun($a, $b);
Stream assignmentlet $x, $y in stream_fun($a, $b);
Usage
Ambiguity
Every function should have a unique name. It’s not allowed to declare two functions with the same name even if they have totally different arguments and return types.
Using Functions at Query-Level
Functions can be defined temporarily at the query level using the with
clause, becoming a with pipeline stage.
Such functions exist only for the duration of the query and are not persisted in the database.
Multiple with
clauses can be used, each defining a single function.
All with
clauses must precede the query pipeline.
with <f1-declaration>
with <f2-declaration>
...
with <fN-declaration>
match
$f1 = f1();
$f2 = f2();
...
$fN = fN();
For example, the following read pipeline defines and uses a temporary function using the with
clause:
with fun karma_with_squared_value($user: user) -> karma, double:
match
$user has karma $karma;
let $karma-squared = $karma * $karma;
return first $karma, $karma-squared;
match
$user isa user, has username $name;
let $karma, $karma-squared = karma_with_squared_value($user);
select $name, $karma-squared;
Using Functions in definition queries
Define
In addition to temporary query-level functions, functions can be persisted in schemas.
Replace the keyword with
with define
and execute the query in a schema transaction:
define
fun karma_with_squared_value($user: user) -> karma, double:
match
$user has karma $karma;
let $karma-squared = $karma * $karma;
return first $karma, $karma-squared;
Once persisted, these functions can be called directly in read queries:
match
$user isa user, has username $name;
let $karma, $karma-squared = karma_with_squared_value($user);
select $name, $karma-squared;