# Functions and actions

You write behaviour in three kinds of callable:

- A **function** is pure: it works out a result from its arguments and
  nothing else.
- An **action** is an operation of your app. It may read and write stored
  data, call outside services and call other actions.
- A **query** reads stored data and never changes it
  ([Named queries](named-queries.md)).

Here is a function:

```jadpo
/// Total for one order line before discounts.
function stock_needed(per_pack: Stock, packs: Quantity) -> Stock {
    var total: Stock = Stock(per_pack * packs)
    return total
}
```

And an action, which loads a todo, changes it and returns a view of it:

```jadpo
action complete_todo(todo_id: Todo.id) fails TodoNotFound -> TodoView {
    var todo: Todo = attempt Todo.get(todo_id)
    var done: Todo = Todo.update(todo) {
        set: {
            status: TodoStatus.done
        }
    }
    return TodoView(done)
}
```

Each kind may call only some of the others:

| Caller | May call | May not |
|---|---|---|
| `function` | functions, library functions, the standard library | actions, queries, stored data, outside services, `clock.now` |
| `query` | functions and queries | actions, writes |
| `action` | functions, queries and actions | |
| A route's `run:` | one action | a function or query directly ([What a route runs](what-a-route-runs.md)) |

A function may still fail: it can declare `fails` and `reject`
([Failures](failures.md)). There is no `async`, `await` or promise:
every call finishes before the caller carries on.

## Signatures and settings

Parameters are positional, and every one has a type. The result type
follows `->`, and `fails` comes before it. A callable that returns nothing
returns `Unit`. Parameters have no defaults.

```jadpo
action reschedule(todo_id: Todo.id, due_at: DueAt) fails TodoNotFound, DueDateInPast -> TodoView {
    var todo: Todo = attempt Todo.get(todo_id)
    ...
}
```

Your own callables are called with positional arguments. Named arguments
exist only for standard-library operations, such as
`temporal.resolve(date: d, zone: z, ...)`.

The whole signature is on the header line, and an action has no settings,
because the safe choice is already the default:

- every action is all-or-nothing;
- every write checks that no one else changed the record since it was
  read;
- every read is current.

[All-or-nothing actions and concurrent changes](all-or-nothing-actions-and-concurrent-changes.md)
has the details. Who may call an action is set by
[Policy](policy.md), not by the action.

When a header is too long, the formatter puts one parameter on each line
and keeps `fails` and `->` after the closing bracket.

## Calling

What comes before the dot names the owner of what you call. Inside your
own domain (a business area of your app, a folder under `domains/`; see
[Project layout](project-layout.md)), you
call its actions and queries by name alone. A helper function used only
in its own file is called the same way.

A helper that several files share lives in a `library`, a named group of
functions and constants, and is called through it, as the standard
library is. Another domain's public actions are called through that
domain's name.

```jadpo
library rounding {
    function half_even(amount: ItemPrice) -> ItemPrice { ... }
}

var total: ItemPrice = rounding.half_even(subtotal)
var line: Stock = stock_needed(per_pack, packs)
var stock: Reservation = attempt inventory.reserve_for_cart(cart)
var todo: Todo = attempt Todo.get(todo_id)
var local: ZonedTime = temporal.in_zone(at, zone)
```

In order, those calls are: a function in the `rounding` library, a helper
in this file, an action of the `inventory` domain, an operation every
entity gets, and the standard library.

A library holds only functions and constants (see [Constants](constants.md)).
