# `Unity`
[🔗](https://github.com/elixir-localize/unity/blob/v0.6.0/lib/unity.ex#L1)

An Elixir unit conversion calculator inspired by the Unix `units` utility.

Uses `Localize.Unit` as the primary engine for unit creation, conversion,
arithmetic, and localized output. Adds a NimbleParsec-based expression
parser and an interpreter that evaluates unit expressions interactively
or from the command line.

## Quick start

    iex> result = Unity.eval!("3 meters to feet")
    iex> result.name
    "foot"

    iex> Unity.eval!("60 mph to km/h") |> Unity.format!()
    "96.56064 kilometers per hour"

## Expression syntax

* `3 meters to feet` — unit conversion.

* `60 mph + 10 km/h` — arithmetic on compatible units.

* `100 kg * 9.8 m/s^2` — unit multiplication.

* `sqrt(9 m^2)` — built-in functions.

* `1|3 cup` — rational numbers.

* `let x = 42 km` — variable binding.

# `env`

```elixir
@type env() :: Unity.Interpreter.env()
```

# `result`

```elixir
@type result() :: Localize.Unit.t() | number() | {:decomposed, [Localize.Unit.t()]}
```

# `eval`

```elixir
@spec eval(String.t(), env()) :: {:ok, result(), env()} | {:error, String.t()}
```

Parses and evaluates a unit expression string.

### Arguments

* `input` - the expression string to evaluate.

* `environment` - a map of variable bindings. Defaults to `%{}`.

### Returns

* `{:ok, result, environment}` on success.

* `{:error, message}` on failure.

### Examples

    iex> {:ok, result, _env} = Unity.eval("3 meters to feet")
    iex> Float.round(result.value, 2)
    9.84

# `eval!`

```elixir
@spec eval!(String.t(), env()) :: result()
```

Parses and evaluates a unit expression string, raising on failure.

### Arguments

* `input` - the expression string to evaluate.

* `environment` - a map of variable bindings. Defaults to `%{}`.

### Returns

The evaluation result (`Localize.Unit.t()` or a number).

### Examples

    iex> result = Unity.eval!("3 meters to feet")
    iex> result.name
    "foot"

# `format`

```elixir
@spec format(
  result(),
  keyword()
) :: {:ok, String.t()} | {:error, String.t()}
```

Formats a result value for display.

Delegates to `Unity.Formatter.format/2`.

### Arguments

* `result` - a `Localize.Unit.t()` or a number.

* `options` - formatting options. See `Unity.Formatter.format/2`.

### Returns

* `{:ok, formatted_string}` on success.

* `{:error, reason}` on failure.

### Examples

    iex> {:ok, unit} = Localize.Unit.new(9.84252, "foot")
    iex> Unity.format(unit)
    {:ok, "9.84252 feet"}

# `format!`

```elixir
@spec format!(
  result(),
  keyword()
) :: String.t()
```

Formats a result value for display, raising on failure.

### Arguments

* `result` - a `Localize.Unit.t()` or a number.

* `options` - formatting options. See `Unity.Formatter.format/2`.

### Returns

The formatted string.

### Examples

    iex> {:ok, unit} = Localize.Unit.new(9.84252, "foot")
    iex> Unity.format!(unit)
    "9.84252 feet"

---

*Consult [api-reference.md](api-reference.md) for complete listing*
