Officially out now: The TypeDB 3.0 Roadmap >>

Scalar and tuple functions

Scalar and tuple functions are function types which return at most one row of outputs.

Syntax

Single functions can be identified by their return type not containing curly braces {}.

Scalar function return format
<return-type>
Tuple function return format
<return-type-0>, ..., <return-type-N>

Usage

Single functions are defined and called like any other function. To retrieve the results of the called function, a simple assignment is enough (however, a general in used for streamed results is also allowed).

Transforming stream outputs to single outputs

TypeQL pipelines generally produce streams of results as not every query always returns a specific number of answers. For example, the following example uses a query with a number of results based on the actual data and does not depend on schema constraints:

match
  $user isa user;

There are two main ways of transforming streams into single results: aggregation and stream modification.

Aggregation

A common case of single functions usage is calling for built-in aggregation functions. These aggregations are usually scalar single functions by themselves, so calling them to aggregate a stream is a natural operation.

Example of an aggregate function used in a scalar function
  fun mean_karma() -> double:
    match
      $user isa user, has karma $karma;
    return mean($karma);
Example of an aggregate function used in a tuple function
  fun karma_sum_and_sum_squares() -> double, double:
    match
      $karma isa karma;
      let $karma-squared = $karma * $karma;
    return sum($karma), sum($karma-squared);

Stream modification

Imagine having function based on a query from the previous example. As already discussed, this function should return a stream of answers.

  fun users() -> { user }:
    match
      $user isa user;
    return { $user };

To make sure that there is maximum one result for a function, an instruction for picking this one result in case of ambiguity is required. TypeQL supports two stream modification keywords for these purposes:

  • first

  • last

With the first keyword, only the first result will be consumed from the stream. It can be used in cases when only the first answer is needed or when there cannot be more than one answer.

With the last keyword, the whole stream is consumed, and only its last answer is returned.

Example of a stream modification
  fun first_user() -> user:
    match
      $user isa user;
    return first $user;

Scalar functions

Scalar single functions are used to return a single result for one expression: a variable or a function call. The following example illustrate simple usages of functions for retrieving an integer.

  fun add($x: integer, $y: integer) -> integer:
    match
      let $z = $x + $y;
    return first $z;

To retrieve the results of such functions calls, the following read query can be used:

match
  let $answer = add(2016, 9);

Tuple functions

It is possible to add another dimension to the returned type and enumerate a number of results returned from a function using commas. Tuples can contain any combinations of scalar returned values.

  fun karma_with_squared_value($user: user) -> karma, double:
    match
      $user has karma $karma;
      let $karma-squared = $karma * $karma;
    return first $karma, $karma-squared;

To retrieve the results of such functions calls, the following read query can be used:

match
  $user isa user, has username $name;
  let $karma, $karma-squared = karma_with_squared_value($user);
select $name, $karma-squared;