Functions

View Source

All built-in functions are registered automatically in contexts created with Elex.new_context/0. This page lists every function with its signature and a brief description.

For usage examples, see the Elex.Functions.* module documentation or try functions in Elex.evaluate/2.

Math functions

FunctionDescription
abs(x)Absolute value
ceil(x)Round up to the nearest integer
floor(x)Round down to the nearest integer
round(x)Round to the nearest integer
sqrt(x)Square root
pow(base, exp)Exponentiation (base raised to exp)
rem(a, b)Remainder; sign follows the dividend (same as %)
mod(a, b)Floored modulo; sign follows the divisor
max(a, b, …)Largest of two or more numbers (variadic)
min(a, b, …)Smallest of two or more numbers (variadic)
clamp(x, min, max)Clamp x to an inclusive [min, max] range
between(x, low, high)true when x is in the inclusive [low, high] range
pi()Mathematical constant π
if(cond, a, b)Conditional; short-circuits; both branches must share a type

rem vs mod vs %

All three perform division-related operations on decimals, but they differ in how they handle signs:

# rem and % — sign follows the dividend
Elex.evaluate("rem(-10, 3)", context)   # #Decimal<-1>
Elex.evaluate("-10 % 3", context)       # #Decimal<-1>

# mod — sign follows the divisor (floored modulo)
Elex.evaluate("mod(-10, 3)", context)   # #Decimal<2>

clamp and between

clamp(x, min, max) returns x bounded to [min, max]. Returns an error when min > max.

between(x, low, high) returns true when low <= x <= high, and false otherwise. Also returns an error when low > high.

Examples

context = Elex.new_context()

{:ok, result} = Elex.evaluate("max(10, 20)", context)           # #Decimal<20>
{:ok, result} = Elex.evaluate("max(3, 7, 9)", context)           # #Decimal<9>
{:ok, result} = Elex.evaluate("abs(-5)", context)                  # #Decimal<5>
{:ok, result} = Elex.evaluate("pow(2, 3)", context)              # #Decimal<8>
{:ok, result} = Elex.evaluate("clamp(15, 0, 10)", context)      # #Decimal<10>
{:ok, result} = Elex.evaluate("between(5, 0, 10)", context)    # true
{:ok, result} = Elex.evaluate("if(10 > 5, 1, 0)", context)      # #Decimal<1>
{:ok, result} = Elex.evaluate("pi()", context)                    # #Decimal<3.14159…>

String functions

FunctionDescription
concat(a, b)Concatenate two strings
length(s)Character count (returns a decimal)
contains(haystack, needle)true when needle is a substring of haystack
starts_with(s, prefix)Prefix test
ends_with(s, suffix)Suffix test
lower(s)Lowercase transform
upper(s)Uppercase transform
trim(s)Remove leading and trailing whitespace
coalesce(a, b, …)First non-null argument (variadic; short-circuits)

Examples

context = Elex.new_context()

{:ok, result} = Elex.evaluate(~s[concat("hello", " world")], context)   # "hello world"
{:ok, result} = Elex.evaluate(~s[length("abc")], context)              # #Decimal<3>
{:ok, result} = Elex.evaluate(~s[contains("hello", "ell")], context)   # true
{:ok, result} = Elex.evaluate(~s[lower("ABC")], context)              # "abc"
{:ok, result} = Elex.evaluate("coalesce(null, 5)", context)            # #Decimal<5>

Custom functions

Implement the Elex.Function behaviour and register your module on the context. See Advanced Topics for a complete example.

Custom functions sit alongside built-ins in the same context and follow the same validation rules: arguments are type-checked at parse time, then evaluated at runtime.

Further reading