README.md

# future

[![Package Version](https://img.shields.io/hexpm/v/future)](https://hex.pm/packages/future)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/future/)

```sh
gleam add future@1
```

## Usage

### Creating a future

```gleam
import future

pub fn to_run(x: Int) -> Result(Int, Nil) {
  Ok(x + x)
}

pub fn main() {
  /// To create a future you must provide a function that takes a single argument and returns a Result
  /// The first argument is the argument passed to the future
  /// Nil is valid as an argument an as wrapped by the returned Result
  let fut = future.new(to_run, 1)

  case future.status(fut) {
    /// The future is still running
    future.Running -> todo
    /// The future has completed and returned a result
    future.Completed(result) ->
      case result {
        /// We can now access the result of the future
        Ok(x) -> todo
        /// The functon doesn't ever return an error so we can just add a guard
        Error(x) -> panic as "An error occured!"
      }
    /// Failures are triggered by two things:
    /// - An external exception was thrown
    /// - Gleam called a panic
    /// If an external exception was thrown then the reason will be a stringified version of the exception
    /// If Gleam called a panic then the reason will be the message passed to the panic
    future.Failed(reason) -> panic as reason
    /// The future is no longer in memory and it's status cannot be used
    future.Released -> panic as "The future has been released"
  }
  {
    use value <- future.then(fut)
    /// The future has been completed and the result is available
    /// We can now access the result of the future
    /// This will return a new future that won't start executing until the prior future has completed
    todo
  }
  {
    use message <- future.add_failure_handler(fut)
    /// The future has failed for the provided reason
    /// We can now access the reason for the failure
    /// This will return nothing
    todo
  }
  {
    use state <- future.after(fut)
    /// The future has completed and a final status is available
    /// This will return nothing
    todo
  }

  /// You should always release the future when you are done with it as erlang will keep it in memory forever otherwise
  /// If you don't want to manually release memory look towards `auto_release`, it releases the future as soon as it's complete. This still allows for chaining futures with `then` (assuming the prior future doesn't exit immediately) but ensures the future is released as soon as possible.
  fut |> future.release
}
```

### Resolving a future immediately

```gleam
import future

pub fn main() {
  /// The result will be immediately available via status
  /// It will also never be marked as running
  let fut = future.from_result(Ok(1)) // This can be an Error too!
  /// Do still make sure to release the future
  fut |> future.release
}
```

```gleam
import future

pub fn main() {
  /// The failure message will be immediately available via status
  /// It will also never be marked as running
  let fut = future.from_failure("example")
  /// Do still make sure to release the future
  fut |> future.release
}
```

### Manually controlling a future

```gleam
import future
import future/manual

pub fn main() {
  /// Create a future that only completes when you call a function
  let #(resolve, reject, fail, fut) = manual.new()

  /// Only the first function to be called will be the result of the future
  /// Any further calls will be ignored
  resolve("hi") // Will complete the future with Ok("hi")
  reject("bye") // Will complete the future with Error("bye")
  fail("oh no") // Will fail the future with Failed("oh no")

  /// Release the future when you are done with it
  fut |> future.release
}
```

### Using a delay

```gleam
import future
import future/delay

pub fn main() {
  /// Creates a future that resolves after the provided duration
  /// This is designed for use with `after` or `then` to delay the execution of some code
  let fut = delay.of(1000)
  /// Do still make sure to release the future
  fut |> future.release
}
```

## Supported runtimes

|Runtime|Supported|
|---|---|
|Erlang|✅|
|Node|✅|
|Deno|✅|
|Bun|✅|

## Contributing

PRs are welcome with or without prior discussion.

## License

This project is licensed under the Apache License, Version 2.0.

See [LICENSE](LICENSE) for more information.

## Additional information

If you're unsure about anything, contact me directly via BradBot_1#2042

Further documentation can be found at <https://hexdocs.pm/future>.