Getting Started

View Source

This guide walks through the most common way to use Elex: parse, validate, and evaluate expression strings with variables.

Installation

Add elex to your mix.exs dependencies:

def deps do
  [
    {:elex, "~> 0.2.0"}
  ]
end

If you plan to use Ash resource validation, also add Ash (Elex treats it as an optional dependency):

{:ash, "~> 3.22"}

Your first expression

Create a context, add variables, and evaluate a formula:

context =
  Elex.new_context()
  |> Elex.add_variable("price", 100)
  |> Elex.add_variable("tax_rate", 0.08)

{:ok, result} = Elex.evaluate("price * (1 + tax_rate)", context)
# result => #Decimal<108>

Elex.evaluate/2 always returns {:ok, result} on success or {:error, reason} on failure. Arithmetic uses the Decimal library, so numeric results are Decimal structs rather than floats.

Building a context

Elex.new_context/0 creates a context with all built-in functions already registered. Add variables one at a time or in bulk:

context =
  Elex.new_context()
  |> Elex.add_variable("quantity", 3)
  |> Elex.add_variables(%{"price" => 10, "discount" => 0.1})

Elex.add_variable/3 infers the variable type from the Elixir value:

Elixir valueInferred type
integer, float, Decimal:decimal
string:string
boolean:boolean
nilnil
anything else:unknown

For precise control, build a %Elex.Variable{} struct and use Elex.Context.add_variable/3 instead.

Validating without evaluating

Use Elex.validate/2 when you need to check syntax and types but not compute a result — for example, validating user input in a form:

context = Elex.new_context() |> Elex.add_variable("price", 100)

{:ok, :decimal} = Elex.validate("price + 10", context)
{:ok, :boolean} = Elex.validate("price > 50", context)
{:error, reason} = Elex.validate("price + \"oops\"", context)

The returned type is one of :decimal, :boolean, :string, or nil (for expressions whose result is null).

Discovering variables

Extract variable names from an expression without requiring them to exist in a context:

{:ok, ["price", "quantity"]} = Elex.extract_variables("price * quantity")

This is useful for building UIs that prompt users to supply values for every referenced name.

Handling errors

Parse, validation, and evaluation errors all come back as {:error, reason} strings from Elex.evaluate/2 and Elex.validate/2:

# Parse error
{:error, "closing parenthesis is missing"} = Elex.evaluate("(1 + 2", context)

# Validation error
{:error, "variable 'missing' does not exist"} = Elex.evaluate("missing + 1", context)

# Evaluation error (e.g. division by zero)
{:error, "Evaluation error: ..."} = Elex.evaluate("1 / 0", context)

Error messages are written for humans writing expressions, not for debugging the parser grammar.

For the full API reference, see the Elex module documentation.