Skip to main content

Standard Library Reference

The constellation-lang standard library provides commonly-used functions for pipeline orchestration.

Most Commonly Used Functions

The functions you will use most often are: add, concat, gt/lt for comparisons, and/or/not for boolean logic, and list-length/list-first for collections. Start with these before exploring the full library.

Finding the Right Function​

By Task​

I want to...FunctionExample
Transform textUppercase, Lowercase, TrimUppercase("hello") → "HELLO"
Work with numbersAdd, Multiply, Max, MinAdd(1, 2) → 3
Process listsMap, Filter, Reduce, LengthLength([1,2,3]) → 3
Format stringsConcat, FormatConcat("a", "b") → "ab"
Handle nullsCoalesce, IsEmptyCoalesce(null, "default")
Compare valuesEquals, GreaterThan, ContainsContains("abc", "b") → true

By Category​

The standard library is organized into categories:

  • String functions — Text manipulation and formatting
  • Numeric functions — Arithmetic and math operations
  • List functions — Collection processing with higher-order functions
  • Logic functions — Boolean operations and comparisons
  • Utility functions — Type conversion and null handling

Using the Standard Library​

Quick Start​

import io.constellation.lang.stdlib.StdLib

// Create a compiler with all stdlib functions registered
val compiler = StdLib.compiler

val source = """
in a: Int
in b: Int
sum = add(a, b)
isGreater = gt(sum, b)
out isGreater
"""

compiler.compile(source, "my-dag")

Selective Registration​

Register only specific functions:

import io.constellation.lang.LangCompiler
import io.constellation.lang.stdlib._

val compiler = LangCompilerBuilder()
.withFunction(MathOps.addSignature)
.withFunction(MathOps.subtractSignature)
.withFunction(CompareOps.gtSignature)
.build

Function Reference​

Type Signature Convention

Type signatures use arrow notation: (param1: Type1, param2: Type2) -> ReturnType. Generic types like List<Int> indicate the element type. All functions are pure unless noted otherwise.

Math Operations​

FunctionType SignatureDescription
add(a: Int, b: Int) -> IntAdd two integers
subtract(a: Int, b: Int) -> IntSubtract b from a
multiply(a: Int, b: Int) -> IntMultiply two integers
divide(a: Int, b: Int) -> IntInteger division
max(a: Int, b: Int) -> IntMaximum of two integers
min(a: Int, b: Int) -> IntMinimum of two integers
abs(value: Int) -> IntAbsolute value
modulo(a: Int, b: Int) -> IntRemainder after division
round(value: Float) -> IntRound float to nearest integer
negate(value: Int) -> IntNegate a number

Error Behavior​

FunctionError ConditionBehavior
divideb = 0Raises ArithmeticException with message "Division by zero in stdlib.divide"
modulob = 0Raises ArithmeticException with message "Division by zero in stdlib.modulo"

Edge Cases​

FunctionEdge CaseResult
addadd(0, 0)0
addLarge numbers near Long.MaxValueMay overflow (no bounds checking)
subtractsubtract(-5, -3)-2
multiplymultiply(x, 0)0
multiplymultiply(-4, -3)12
dividedivide(0, 5)0
dividedivide(7, 3)2 (truncates toward zero)
dividedivide(-10, 3)-3 (truncates toward zero)
maxmax(5, 5)5
maxmax(-10, -5)-5
minmin(5, 5)5
minmin(-10, -5)-10
absabs(0)0
absabs(-5)5
absabs(Long.MinValue)Undefined (overflow)
modulomodulo(6, 3)0 (exact divisibility)
negatenegate(0)0
negatenegate(-5)5
roundround(3.5)4 (rounds half up)
roundround(-2.7)-3

Performance Notes​

All math operations are O(1) pure functions with no memory allocation beyond the result.

Examples:

in x: Int
in y: Int

sum = add(x, y)
diff = subtract(x, y)
product = multiply(x, y)
quotient = divide(x, y)
maximum = max(x, y)
minimum = min(x, y)
absolute = abs(x)
remainder = modulo(x, y)
negated = negate(x)

out sum

Safe Division Pattern:

in numerator: Int
in denominator: Int

# Check for zero before dividing to avoid runtime errors
isZero = eq-int(denominator, 0)
safeResult = if (isZero) 0 else divide(numerator, denominator)

out safeResult

String Operations​

FunctionType SignatureDescription
concat(a: String, b: String) -> StringConcatenate two strings
string-length(value: String) -> IntGet string length (character count)
join(list: List<String>, separator: String) -> StringJoin strings with delimiter
split(value: String, substring: String) -> List<String>Split string by delimiter
contains(value: String, substring: String) -> BooleanCheck if string contains substring
trim(value: String) -> StringTrim leading and trailing whitespace
replace(value: String, target: String, replacement: String) -> StringReplace all occurrences

Edge Cases​

FunctionEdge CaseResult
concatconcat("", "")""
concatconcat("", "hello")"hello"
concatUnicode stringsFully supported
string-lengthstring-length("")0
string-lengthUnicode (e.g., Chinese)Character count, not byte count
string-lengthstring-length("hello world")11 (includes space)
joinEmpty list""
joinSingle element listElement without separator
splitEmpty delimiterReturns original string in single-element list
splitDelimiter not foundReturns original string in single-element list
splitConsecutive delimitersIncludes empty strings in result
containscontains("hello", "")true (empty string is always contained)
containscontains("", "x")false
trimtrim("")""
trimtrim(" ")"" (whitespace-only becomes empty)
trimtrim(" hello ")"hello"
replaceNo match foundReturns original string unchanged
replacereplace("aaa", "a", "b")"bbb" (replaces all occurrences)

Error Guarantees​

All string operations are safe and never raise exceptions. They handle empty strings and Unicode gracefully.

Performance Notes​

  • concat: O(n+m) where n and m are string lengths
  • string-length: O(1)
  • join: O(total length of all strings)
  • split: O(n) where n is string length; uses regex quoting internally for safe literal matching
  • contains: O(n*m) worst case
  • trim: O(n)
  • replace: O(n*m) worst case, creates new string

Examples:

in firstName: String
in lastName: String

fullName = concat(firstName, lastName)
nameLength = string-length(fullName)
trimmed = trim(fullName)
hasSpace = contains(fullName, " ")
cleaned = replace(fullName, " ", "-")

out fullName

Joining a List of Strings:

in words: List<String>
in separator: String

sentence = join(words, separator)

out sentence

Splitting a String:

in csv: String

# Split CSV line by comma
fields = split(csv, ",")

out fields

Boolean Operations​

FunctionType SignatureDescription
and(a: Boolean, b: Boolean) -> BooleanLogical AND
or(a: Boolean, b: Boolean) -> BooleanLogical OR
not(value: Boolean) -> BooleanLogical NOT

Truth Tables​

and(a, b):

abResult
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

or(a, b):

abResult
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

not(value):

valueResult
truefalse
falsetrue

Error Guarantees​

Boolean operations are always safe and cannot fail.

Performance Notes​

All boolean operations are O(1) constant time, pure functions.

Examples:

in isActive: Boolean
in isVerified: Boolean

canProceed = and(isActive, isVerified)
hasAccess = or(isActive, isVerified)
isInactive = not(isActive)

out canProceed

Comparison Operations​

FunctionType SignatureDescription
eq-int(a: Int, b: Int) -> BooleanCheck if integers are equal
eq-string(a: String, b: String) -> BooleanCheck if strings are equal
gt(a: Int, b: Int) -> BooleanCheck if a > b
lt(a: Int, b: Int) -> BooleanCheck if a < b
gte(a: Int, b: Int) -> BooleanCheck if a >= b
lte(a: Int, b: Int) -> BooleanCheck if a <= b

Edge Cases​

FunctionEdge CaseResult
eq-inteq-int(0, 0)true
eq-inteq-int(-5, -5)true
eq-stringeq-string("", "")true
eq-stringeq-string("Hello", "hello")false (case-sensitive)
eq-stringUnicode stringsFully supported
gtgt(5, 5)false
gtgt(-5, -10)true
ltlt(5, 5)false
ltlt(-10, -5)true
gtegte(5, 5)true
ltelte(5, 5)true

Error Guarantees​

Comparison operations are always safe and cannot fail.

Performance Notes​

All comparison operations are O(1) for integers. String equality is O(min(n,m)) where n and m are string lengths.

Examples:

in score: Int
in threshold: Int
in expected: String
in actual: String

isAbove = gt(score, threshold)
isBelow = lt(score, threshold)
isEqual = eq-int(score, threshold)
matches = eq-string(expected, actual)

# Use with conditional
result = if (isAbove) score else threshold

out result

List Operations​

FunctionType SignatureDescription
list-length(list: List<Int>) -> IntGet list length
list-first(list: List<Int>) -> IntGet first element
list-last(list: List<Int>) -> IntGet last element
list-is-empty(list: List<Int>) -> BooleanCheck if list is empty
list-sum(list: List<Int>) -> IntSum all elements
list-concat(a: List<Int>, b: List<Int>) -> List<Int>Concatenate two lists
list-contains(list: List<Int>, value: Int) -> BooleanCheck if element exists
list-reverse(list: List<Int>) -> List<Int>Reverse list order

Error Behavior​

FunctionError ConditionBehavior
list-firstEmpty listRaises NoSuchElementException with message "stdlib.list-first: list is empty"
list-lastEmpty listRaises NoSuchElementException with message "stdlib.list-last: list is empty"

Edge Cases​

FunctionEdge CaseResult
list-lengthEmpty list0
list-lengthSingle element1
list-is-emptyEmpty listtrue
list-is-emptyNon-empty listfalse
list-sumEmpty list0 (identity for addition)
list-sumNegative numbersSummed correctly
list-containsEmpty listfalse
list-reverseEmpty list[] (empty list)
list-reverseSingle elementSame list
list-concatBoth empty[]
list-concatFirst emptyReturns second list
list-concatSecond emptyReturns first list

Safe List Access Pattern​

in numbers: List<Int>

# Always check before accessing first/last
isEmpty = list-is-empty(numbers)
safeFirst = if (isEmpty) 0 else list-first(numbers)

out safeFirst

Performance Notes​

FunctionTime ComplexitySpace Complexity
list-lengthO(1)O(1)
list-firstO(1)O(1)
list-lastO(1)O(1)
list-is-emptyO(1)O(1)
list-sumO(n)O(1)
list-concatO(n+m)O(n+m)
list-containsO(n)O(1)
list-reverseO(n)O(n)

Examples:

in numbers: List<Int>

count = list-length(numbers)
first = list-first(numbers)
last = list-last(numbers)
isEmpty = list-is-empty(numbers)
total = list-sum(numbers)
reversed = list-reverse(numbers)

out count

Concatenating Lists:

in listA: List<Int>
in listB: List<Int>

combined = list-concat(listA, listB)

out combined

Type Conversion Operations​

FunctionType SignatureDescription
to-string(value: Int) -> StringConvert integer to string
to-int(value: Float) -> IntTruncate float to integer
to-float(value: Int) -> FloatConvert integer to float

Edge Cases​

FunctionEdge CaseResult
to-stringto-string(0)"0"
to-stringto-string(-7)"-7"
to-intto-int(3.7)3 (truncates toward zero)
to-intto-int(-3.7)-3 (truncates toward zero)
to-intto-int(0.0)0
to-floatto-float(0)0.0
to-floatto-float(-7)-7.0

Error Guarantees​

Type conversion operations are always safe and cannot fail.

Note: to-int truncates toward zero (not floor), so -3.7 becomes -3, not -4.

Performance Notes​

All type conversions are O(1) except to-string which is O(log n) where n is the magnitude of the integer.

Examples:

in count: Int
in measurement: Float

label = to-string(count)
truncated = to-int(measurement)
precise = to-float(count)

out label

Higher-Order Functions​

tip

Higher-order functions like filter, map, all, and any are processed specially by the compiler and use InlineTransform at runtime. They short-circuit when possible (e.g., any stops on first true).

FunctionType SignatureDescription
filter(List<Int>, (Int) => Boolean) -> List<Int>Keep elements matching predicate
map(List<Int>, (Int) => Int) -> List<Int>Transform each element
all(List<Int>, (Int) => Boolean) -> BooleanCheck all elements match
any(List<Int>, (Int) => Boolean) -> BooleanCheck any element matches

Edge Cases​

FunctionEdge CaseResult
filterEmpty list[]
filterNo matches[]
mapEmpty list[]
allEmpty listtrue (vacuous truth)
anyEmpty listfalse

Implementation Notes​

Higher-order functions are processed specially by the compiler. They use InlineTransform at runtime (e.g., FilterTransform, MapTransform) rather than traditional Module implementations.

Performance Notes​

FunctionTime ComplexitySpace Complexity
filterO(n)O(k) where k = matching elements
mapO(n)O(n)
allO(n) worst case, short-circuits on first falseO(1)
anyO(n) worst case, short-circuits on first trueO(1)

Examples:

use stdlib.collection
use stdlib.compare
use stdlib.math

in numbers: List<Int>

positives = filter(numbers, (x) => gt(x, 0))
doubled = map(numbers, (x) => multiply(x, 2))
allPositive = all(numbers, (x) => gt(x, 0))
anyNegative = any(numbers, (x) => lt(x, 0))

out positives

Chaining Higher-Order Functions:

use stdlib.collection
use stdlib.compare
use stdlib.math

in numbers: List<Int>

# Filter then map: get absolute values of negative numbers
negatives = filter(numbers, (x) => lt(x, 0))
absolutes = map(negatives, (x) => abs(x))

out absolutes

Utility Operations​

FunctionType SignatureDescription
identity(value: String) -> StringPass-through (returns input unchanged)
log(message: String) -> StringLog message and pass through

Edge Cases​

FunctionEdge CaseResult
identityEmpty string""
identityUnicodePassed through unchanged
logEmpty messageLogs empty line, returns ""

Error Guarantees​

Utility operations are always safe and cannot fail.

Implementation Notes​

  • identity is a pure function with no side effects
  • log prints to stdout with prefix [constellation-lang] and returns the input unchanged

Examples:

in message: String

# Log for debugging
logged = log(message)

# Identity (useful for type coercion or pipeline passthrough)
same = identity(message)

out logged

Common Patterns​

Conditional Logic with Comparisons​

in score: Int

threshold = 50
isPass = gt(score, threshold)
result = if (isPass) score else threshold

out result

Chaining Operations​

in a: Int
in b: Int
in c: Int

# Compute (a + b) * c
sum = add(a, b)
product = multiply(sum, c)

out product

String Processing​

in firstName: String
in lastName: String

# Create "lastName, firstName"
separator = ", "
temp = concat(lastName, separator)
fullName = concat(temp, firstName)
trimmed = trim(fullName)

out trimmed

Boolean Gates​

in isAuthenticated: Boolean
in hasPermission: Boolean
in isAdmin: Boolean

# Check: (authenticated AND permission) OR admin
hasAccess = and(isAuthenticated, hasPermission)
canProceed = or(hasAccess, isAdmin)

out canProceed

Safe Division​

in numerator: Int
in denominator: Int

# Avoid division by zero
isZero = eq-int(denominator, 0)
safeQuotient = if (isZero) 0 else divide(numerator, denominator)

out safeQuotient

Safe List Access​

in numbers: List<Int>

# Get first element or default to 0
isEmpty = list-is-empty(numbers)
firstOrDefault = if (isEmpty) 0 else list-first(numbers)

out firstOrDefault

Data Aggregation​

in values: List<Int>

count = list-length(values)
total = list-sum(values)

# Note: For average, you'd need float division which requires
# converting total to float first
totalFloat = to-float(total)
countFloat = to-float(count)

out total

Namespaces​

All stdlib functions are organized into namespaces:

NamespaceFunctions
stdlib.mathadd, subtract, multiply, divide, max, min, abs, modulo, round, negate
stdlib.stringconcat, string-length, join, split, contains, trim, replace
stdlib.compareeq-int, eq-string, gt, lt, gte, lte
stdlib.booland, or, not
stdlib.listlist-length, list-first, list-last, list-is-empty, list-sum, list-concat, list-contains, list-reverse
stdlib.collectionfilter, map, all, any
stdlib.convertto-string, to-int, to-float
stdlibidentity
stdlib.debuglog

Module Details​

Each stdlib function is implemented as a Constellation module. The modules are registered with these names:

FunctionModule Name
addstdlib.add
subtractstdlib.subtract
multiplystdlib.multiply
dividestdlib.divide
maxstdlib.max
minstdlib.min
absstdlib.abs
modulostdlib.modulo
roundstdlib.round
negatestdlib.negate
concatstdlib.concat
string-lengthstdlib.string-length
joinstdlib.join
splitstdlib.split
containsstdlib.contains
trimstdlib.trim
replacestdlib.replace
andstdlib.and
orstdlib.or
notstdlib.not
eq-intstdlib.eq-int
eq-stringstdlib.eq-string
gtstdlib.gt
ltstdlib.lt
gtestdlib.gte
ltestdlib.lte
list-lengthstdlib.list-length
list-firststdlib.list-first
list-laststdlib.list-last
list-is-emptystdlib.list-is-empty
list-sumstdlib.list-sum
list-concatstdlib.list-concat
list-containsstdlib.list-contains
list-reversestdlib.list-reverse
to-stringstdlib.to-string
to-intstdlib.to-int
to-floatstdlib.to-float
identitystdlib.identity
logstdlib.log

Error Handling Summary​

Functions That Can Raise Errors​

FunctionException TypeConditionMessage
divideArithmeticExceptionDivisor is zero"Division by zero in stdlib.divide"
moduloArithmeticExceptionDivisor is zero"Division by zero in stdlib.modulo"
list-firstNoSuchElementExceptionList is empty"stdlib.list-first: list is empty"
list-lastNoSuchElementExceptionList is empty"stdlib.list-last: list is empty"

Functions That Are Always Safe​

All other functions are guaranteed not to raise exceptions when given valid typed inputs:

  • All math functions except divide and modulo
  • All string functions
  • All boolean functions
  • All comparison functions
  • All list functions except list-first and list-last
  • All type conversion functions
  • All higher-order functions
  • All utility functions

Type System Notes​

Integer Type​

Integers in constellation-lang use Long (64-bit signed) internally:

  • Range: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
  • Overflow behavior: Standard JVM wraparound (no automatic detection)

Float Type​

Floats use Double (64-bit IEEE 754) internally:

  • Full double-precision floating-point support
  • Special values: NaN, Infinity, -Infinity are supported

String Type​

Strings are Java String objects:

  • Full Unicode support (UTF-16 internally)
  • string-length returns character count (Unicode code units), not byte count

List Type​

Lists use immutable Vector[CValue] internally:

  • Efficient random access: O(log n)
  • Efficient append/prepend: O(log n)
  • Memory efficient for large lists

Extending the Standard Library​

Add custom functions following the same pattern:

import io.constellation.ModuleBuilder
import io.constellation.lang.semantic._

object MyModule {
case class In(value: Int)
case class Out(result: Int)

val module = ModuleBuilder
.metadata("my-namespace.my-function", "Description", 1, 0)
.tags("custom")
.implementationPure[In, Out](in => Out(in.value * 2))
.build

val signature = FunctionSignature(
name = "my-function",
params = List("value" -> SemanticType.SInt),
returns = SemanticType.SInt,
moduleName = "my-namespace.my-function"
)
}

Register with the compiler:

val compiler = StdLib.registerAll(LangCompilerBuilder())
.withFunction(MyModule.signature)
.build

Best Practices for Custom Functions​

  1. Use descriptive names - Function names should clearly indicate purpose
  2. Document edge cases - Specify behavior for empty inputs, zeros, etc.
  3. Prefer pure implementations - Use implementationPure when possible
  4. Handle errors gracefully - Raise meaningful exceptions with clear messages
  5. Follow naming conventions - Use lowercase-with-hyphens for function names