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.
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;