# Lesson 10.2: Function chaining

## [](#_simple_function_chaining)Simple function chaining

Much like views in a relational database, which can be generated from other views, functions in TypeDB can leverage answers generated by other functions.

```typeql
fun verified-reviews($book: book) -> { review }:
  match
  $review isa review;
  rating ($review, $book);
  order-line ($order, $book);
  $_ isa action-execution ($user, $review), has timestamp $review-time;
  $_ isa action-execution ($user, $order), has timestamp $order-time;
  $review-time > $order-time;
  return { $review };
```

```typeql
fun unverified-reviews($book: book) -> { review }:
  match
  $review isa review;
  rating ($review, $book);
  not {
    let $verified-review in verified-reviews($book);
    $review is $verified-review;
  };
  return { $review };
```

The unverified-reviews function can re-use the work of the first function, modularizing logic effectively and promoting re-use.

## [](#_recursive_function_chaining)Recursive function chaining

Functions can recurse as well! A recursive function is one which invokes itself.

```typeql
fun transitive_places_unoptimized($place: place) -> { place }:
  match
    {
      locating (located: $place, location: $transitive);
    } or {
      locating (located: $place, location: $next);
      let $transitive in transitive_places_unoptimized($next);
    };
  return { $transitive };
```

Note that this function is written in the **unoptimized** recursive form. Read the [Optimizing TypeQL](../../../guides/typeql/optimizing-typeql/index.md) page to understand how to write this more efficiently.

```typeql
match
$user isa user, has id "u0003";
(located: $user, location: $place) isa locating;
fetch {
  "direct-place": $place.name,
  "transitive-places": [
    match let $transitive in transitive_places_unoptimized($place);
    fetch { "place": $transitive.name };
  ],
};
```

```json
{
  "direct-place": "Newark",
  "transitive-places": [
    {
      "place": "United States"
    },
    {
      "place": "New Jersey"
    }
  ]
}
```

Recursive functions have "self-terminating" behaviours that are guaranteed to reach a fixed point and finish their computation, under the condition that the function isn’t continuously generating new values (or in the future - lists).

In other words, when using functions to simply modularize queries and invoke recursion without computing new data, functions will always terminate - even in the case of data cycles. Beware that passing an incrementing or decrementing integer argument does invalidate this guarantee - which might be what you want!

[Functions as views](../10.1-functions-as-views/index.md) [Summary](../summary/index.md)

[Edit on GitHub](https://github.com/typedb/typedb-docs/edit/3.x-development/academy/modules/ROOT/pages/10-using-functions/10.2-function-chaining.adoc) Edit this page on GitHub.