# Then
Because sometimes you want to do something *after* a function, but don't want to clutter its code.
## Installation
```elixir
def deps do
[{:then, "~> 1.0.0"}]
end
```
## How it works
Put `@then :callback` above a function and it will automatically call `callback(result)` after execution:
```elixir
defmodule MyModule do
use Then
@then :log
def add(a, b) do
a + b
end
def log(result) do
IO.puts("Got #{result}")
end
end
MyModule.add(2, 3)
# Got 5
# => 5
```
Function result stays unchanged, callback is called for side effects.
## Why you need this
For logging, metrics, notifications — all the stuff you don't want mixed with your main logic:
```elixir
defmodule UserService do
use Then
@then :audit_creation
def new_user(params) do
case params do
%{email: email, name: name} -> {:ok, %User{name: name, email: email}}
_ -> {:error, "Required fileds are missing"}
end
end
# side effects separately
def audit_creation({:ok, user}), do: Logger.info("User #{user.email} created")
def audit_creation({:error, reason}), do: Logger.warn("User wasn't created. #{reason}")
end
```
## Limitations
- One `@then` per function (compilation error if you try to use multiple)
- Callback is not called if function raises an exception
- For functions with multiple clauses, `@then` applies to all clauses
## Compatibility
Works perfectly with other function attributes:
```elixir
defmodule MyModule do
use Then
@doc "Gets age from params"
@spec get_age(map()) :: integer()
@then :log_term
def get_age(params) do
params[:age] || 0
end
defp log_term(term), do: IO.puts("[log-term] #{term}")
end
```
`@spec`, `@doc`, `@deprecated` and other attributes work as expected. Callback functions can be private (`defp`).
## Why not just call the callback at the end of the function?
It's simple and clear. Move log and other side-effects out of your beautiful logic.