Zum Inhalt springen
Developer Preview — APIs and language features may change before 1.0

Expression Standard Library

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

mashinTalk’s expression language ships with built-in namespaces, value methods, and global functions. These are language built-ins compiled directly to BEAM code, not mashinTalk machines. They are available in any expression context: compute steps, decide conditions, field defaults, and string interpolation.

Namespaces

Namespaces are called as Namespace.function(args). Available namespaces:

Math DateTime JSON Object Set UUID Intl Result Option String form


Math

Mathematical functions and constants.

FunctionSignatureDescription
Math.abs(x)number -> numberAbsolute value
Math.ceil(x)number -> integerRound up to nearest integer
Math.floor(x)number -> integerRound down to nearest integer
Math.round(x)number -> integerRound to nearest integer
Math.round(x, precision)number, integer -> floatRound to given decimal places
Math.max(a, b)number, number -> numberLarger of two values
Math.min(a, b)number, number -> numberSmaller of two values
Math.pow(base, exp)number, number -> floatBase raised to exponent
Math.sqrt(x)number -> floatSquare root
Math.log(x)number -> floatNatural logarithm
Math.log2(x)number -> floatBase-2 logarithm
Math.log10(x)number -> floatBase-10 logarithm
Math.exp(x)number -> floate raised to the power x
Math.sin(x)number -> floatSine (radians)
Math.cos(x)number -> floatCosine (radians)
Math.tan(x)number -> floatTangent (radians)
Math.asin(x)number -> floatArcsine
Math.acos(x)number -> floatArccosine
Math.atan(x)number -> floatArctangent
Math.atan2(y, x)number, number -> floatTwo-argument arctangent
Math.trunc(x)number -> integerTruncate decimal part toward zero
Math.sign(x)number -> -1 | 0 | 1Sign of the number
Math.random()-> floatRandom float in [0.0, 1.0)

Constants:

ConstantValueDescription
Math.PI3.14159...Pi
Math.E2.71828...Euler’s number
compute circle_area
let r = input.radius
Math.PI * Math.pow(r, 2)

DateTime

Date and time operations. All functions work with ISO 8601 strings and DateTime values.

FunctionSignatureDescription
DateTime.now()-> stringCurrent UTC datetime as ISO 8601
DateTime.today()-> stringCurrent UTC date as YYYY-MM-DD
DateTime.parse(iso_string)string -> DateTimeParse an ISO 8601 string
DateTime.diff(a, b)DateTime, DateTime -> integerSeconds between a and b
DateTime.add(dt, amount)DateTime, integer -> DateTimeAdd seconds to a datetime
DateTime.add(dt, amount, unit)DateTime, integer, string -> DateTimeAdd with unit: "seconds", "minutes", "hours", "days"
DateTime.isBefore(a, b)DateTime, DateTime -> booleanTrue if a is before b
DateTime.isAfter(a, b)DateTime, DateTime -> booleanTrue if a is after b
DateTime.isBetween(dt, from, to)DateTime, DateTime, DateTime -> booleanTrue if dt is between from and to
DateTime.format(dt, style)DateTime, string -> stringFormat a datetime as a string
DateTime.toUnix(dt)DateTime -> integerConvert to Unix timestamp (seconds)
DateTime.fromUnix(timestamp)integer -> DateTimeConvert from Unix timestamp
DateTime.startOfDay(dt)DateTime -> DateTimeMidnight at the start of the day
DateTime.dayOfWeek(dt)DateTime -> integerDay of week: 1 (Monday) to 7 (Sunday)
DateTime.relative(dt)DateTime -> stringHuman-readable relative time (e.g. “3 hours ago”)
compute time_check
let now = DateTime.now()
let deadline = DateTime.parse(input.due_at)
let overdue = DateTime.isAfter(now, deadline)
{overdue: overdue, seconds_remaining: DateTime.diff(deadline, now)}

JSON

FunctionSignatureDescription
JSON.parse(json_string)string -> anyParse a JSON string into a value
JSON.stringify(value)any -> stringSerialize a value to a JSON string
JSON.stringify(value, indent)any, integer -> stringPretty-print with given indent level

Object

Operations on objects (maps / key-value pairs).

FunctionSignatureDescription
Object.keys(obj)object -> array<string>List all keys
Object.values(obj)object -> array<any>List all values
Object.entries(obj)object -> array<[string, any]>List all [key, value] pairs
Object.fromEntries(entries)array<[string, any]> -> objectBuild an object from entries
Object.merge(target, source)object, object -> objectMerge source into target (source wins on conflict)
Object.assign(target, source)object, object -> objectAlias for merge
Object.hasKey(obj, key)object, string -> booleanTrue if key exists
Object.get(obj, key)object, string -> any | nilGet value or nil if absent
Object.get(obj, key, default)object, string, any -> anyGet value or default if absent
Object.delete(obj, key)object, string -> objectRemove a key, return new object
compute normalize
let keys = Object.keys(input.data)
let entries = Object.entries(input.data)
let cleaned = Object.fromEntries(entries.filter(([k, v]) => v != null))
cleaned

Set

Operations on sets (unordered collections with no duplicates).

FunctionSignatureDescription
Set.from(list)array -> SetCreate a set from a list
Set.has(set, value)Set, any -> booleanTrue if value is in the set
Set.add(set, value)Set, any -> SetAdd a value, return new set
Set.delete(set, value)Set, any -> SetRemove a value, return new set
Set.union(a, b)Set, Set -> SetAll elements in either set
Set.intersection(a, b)Set, Set -> SetElements in both sets
Set.difference(a, b)Set, Set -> SetElements in a but not b
Set.size(set)Set -> integerNumber of elements
Set.toList(set)Set -> arrayConvert to a list

UUID

FunctionSignatureDescription
UUID.generate()-> stringGenerate a random UUID v4
UUID.v4()-> stringAlias for UUID.generate()

Intl

Locale-aware formatting. Uses the machine’s locale when set via written in.

FunctionSignatureDescription
Intl.formatNumber(num)number -> stringFormat a number for display
Intl.formatNumber(num, opts)number, object -> stringFormat with options: opts.decimals (integer) for decimal places, opts.style: "percent" to multiply by 100 and append %
Intl.formatDate(dt)string -> stringFormat a date/datetime string
Intl.formatDate(dt, opts)string, object -> stringFormat with style: "iso", "date", "time", or "short" (default)

Result

Explicit error handling without exceptions. Use Result to represent operations that may succeed or fail.

FunctionSignatureDescription
Result.ok(value)any -> ResultWrap a success value
Result.error(reason)any -> ResultWrap a failure reason
Result.is_ok(r)Result -> booleanTrue if the result is ok
Result.is_error(r)Result -> booleanTrue if the result is an error
Result.map(r, fn)Result, (any) -> any -> ResultTransform the ok value
Result.and_then(r, fn)Result, (any) -> Result -> ResultChain operations that may fail
Result.unwrap_or(r, default)Result, any -> anyExtract value or use default on error
Result.unwrap!(r)Result -> anyExtract value, raise if error
Result.try_fn(fn)(() -> any) -> ResultWrap a function call, catching errors as Result.error
compute safe_parse
let parsed = Result.try_fn(() => JSON.parse(input.payload))
let data = Result.unwrap_or(parsed, {items: []})
{items: data.items}

Option

Explicit null handling. Use Option to represent values that may or may not be present.

FunctionSignatureDescription
Option.some(value)any -> OptionWrap a present value
Option.none()-> OptionRepresent absence
Option.is_some(o)Option -> booleanTrue if value is present
Option.is_none(o)Option -> booleanTrue if value is absent
Option.map(o, fn)Option, (any) -> any -> OptionTransform the inner value if present
Option.and_then(o, fn)Option, (any) -> Option -> OptionChain operations on optional values
Option.unwrap_or(o, default)Option, any -> anyExtract value or use default if absent
Option.from_nullable(value)any | nil -> OptionConvert a nullable value to an Option

String (namespace)

String utility functions callable as String.function(args). See also String value methods for dot-syntax equivalents.

FunctionSignatureDescription
String.join(list, separator)array, string -> stringJoin a list into a string
String.to_string(value)any -> stringCoerce any value to a string
String.split(str, delimiter)string, string -> array<string>Split a string into a list
String.trim(str)string -> stringRemove leading and trailing whitespace
String.replace(str, pattern, replacement)string, string, string -> stringReplace first occurrence
String.length(str)string -> integerCharacter count
String.uppercase(str)string -> stringConvert to uppercase
String.lowercase(str)string -> stringConvert to lowercase

form (Governed Metaprogramming)

The form namespace provides access to machine forms: the AST representation of a mashinTalk machine. Use form functions inside compute steps to inspect, transform, and serialize machine structure. form.eval, form.propose, and form.describe require an ask step because they perform governed effects.

Introspection

FunctionSignatureDescription
form.kind(f)Form -> stringNode type (e.g. "machine", "step", "section")
form.name(f)Form -> stringNode name
form.children(f)Form -> array<Form>Direct children
form.fields(f)Form -> objectField map for the node
form.section(f, name)Form, string -> FormFind a section by name
form.step(f, name)Form, string -> FormFind a step by name
form.steps(f)Form -> array<Form>All steps in the form
form.inputs(f)Form -> array<Form>Input field forms
form.outputs(f)Form -> array<Form>Output field forms
form.get(f, path)Form, string -> anyGet a field value by path

Mutation

All mutation functions return a new Form; the original is unchanged.

FunctionSignatureDescription
form.set(f, path, value)Form, string, any -> FormSet a field at path
form.add(f, child)Form, Form -> FormAppend a child node
form.add(f, position, child)Form, integer, Form -> FormInsert a child at position
form.remove(f, name)Form, string -> FormRemove a child by name
form.replace(f, name, new_form)Form, string, Form -> FormReplace a child by name
form.merge(f1, f2)Form, Form -> FormMerge two forms
form.diff(f1, f2)Form, Form -> objectDiff between two forms
form.insert_before(f, ref, child)Form, string, Form -> FormInsert before a named sibling
form.insert_after(f, ref, child)Form, string, Form -> FormInsert after a named sibling
form.wrap(f, wrapper_kind)Form, string -> FormWrap a form in a new node of the given kind
form.dissoc(f, key)Form, string -> FormRemove a key from fields
form.update(f, key, fn)Form, string, (any) -> any -> FormUpdate a field with a function
form.merge_with(f1, f2, fn)Form, Form, (any, any) -> any -> FormMerge forms using a custom conflict resolver

Serialization

FunctionSignatureDescription
form.to_text(f)Form -> stringSerialize to mashinTalk source
form.to_text(f, opts)Form, object -> stringSerialize with options
form.from_text(text)string -> FormParse mashinTalk source into a form
form.to_json(f)Form -> stringSerialize to JSON
form.from_json(json)string -> FormDeserialize from JSON
form.to_minified(f)Form -> stringMinified mashinTalk source
form.to_node(f)Form -> objectConvert to a plain object node
FunctionSignatureDescription
form.postwalk(f, fn)Form, (Form) -> Form -> FormWalk tree bottom-up, transforming each node
form.prewalk(f, fn)Form, (Form) -> Form -> FormWalk tree top-down, transforming each node
form.flatten(f)Form -> array<Form>All nodes as a flat list
form.clone(f)Form -> FormDeep copy
form.find(f, predicate)Form, (Form) -> boolean -> Form | nilFirst node matching predicate
form.select(f, predicate)Form, (Form) -> boolean -> array<Form>All nodes matching predicate
form.some(f, predicate)Form, (Form) -> boolean -> booleanTrue if any node matches
form.every(f, predicate)Form, (Form) -> boolean -> booleanTrue if all nodes match
form.map_children(f, fn)Form, (Form) -> Form -> FormTransform direct children only
form.flat_map(f, fn)Form, (Form) -> array<Form> -> array<Form>Map then flatten children

Deep Access

FunctionSignatureDescription
form.get_in(f, path)Form, array<string> -> anyGet a nested value by path
form.put_in(f, path, value)Form, array<string>, any -> FormSet a nested value by path
form.update_in(f, path, fn)Form, array<string>, (any) -> any -> FormUpdate a nested value with a function

Construction

FunctionSignatureDescription
form.new(kind, name)string, string -> FormCreate a new form node
form.new(kind, name, fields)string, string, object -> FormCreate with initial fields
form.from_node(node)object -> FormBuild a form from a plain object

Analysis

FunctionSignatureDescription
form.validate(f)Form -> objectValidate; returns {valid: boolean, errors: array}
form.hash(f)Form -> stringContent hash of the form
form.capabilities(f)Form -> array<string>Capabilities declared or used
form.dependencies(f)Form -> array<string>Machine references this form depends on
form.credential_requirements(f)Form -> array<string>Credentials required to run
form.explain(f)Form -> stringHuman-readable description

Composition

FunctionSignatureDescription
form.pipe(f, fns...)Form, ...(Form) -> Form -> FormApply a sequence of transformations

Utilities

FunctionSignatureDescription
form.frequencies(f)Form -> objectMap of node kind to count
form.sort_by(f, fn)Form, (Form) -> any -> array<Form>Sort children by a key function
form.select_keys(f, keys)Form, array<string> -> objectExtract named fields as an object
form.group_by(f, fn)Form, (Form) -> any -> objectGroup nodes by a key function

Zipper (cursor-based traversal)

Zippers let you navigate and edit a form tree by keeping a cursor position. Changes made via a zipper are applied when you call form.root.

FunctionSignatureDescription
form.zipper(f)Form -> ZipperCreate a zipper at the root
form.down(z)Zipper -> ZipperMove to first child
form.up(z)Zipper -> ZipperMove to parent
form.left(z)Zipper -> ZipperMove to left sibling
form.right(z)Zipper -> ZipperMove to right sibling
form.zip_node(z)Zipper -> FormGet the form at the current cursor
form.edit(z, fn)Zipper, (Form) -> Form -> ZipperTransform the current node
form.zip_replace(z, form)Zipper, Form -> ZipperReplace the current node
form.insert_left(z, form)Zipper, Form -> ZipperInsert a sibling to the left
form.insert_right(z, form)Zipper, Form -> ZipperInsert a sibling to the right
form.zip_remove(z)Zipper -> ZipperRemove the current node
form.root(z)Zipper -> FormReturn the full form with all zipper edits applied

Extensions

FunctionSignatureDescription
form.generate_inputs(f)Form -> objectGenerate a sample input object matching the form’s accepts contract
form.apply_rules(f, rules)Form, array -> FormApply a list of transformation rules to the form
form.recommend_supervision(f)Form -> objectSuggest governance settings based on form analysis

Governed effects (require ask step)

These functions perform governed effects and cannot be called in a compute step. Use them inside an ask step.

FunctionDescription
form.eval(f, input)Execute the form with a given input object
form.propose(f, name)Propose the form for promotion under a given name
form.describe(machine_ref)Load and describe a machine by reference

Value Methods

Value methods are called on a value using dot syntax: value.method(args).


Array Methods

Methods available on any array value.

MethodSignatureDescription
.map(fn)(any) -> any -> arrayTransform each element
.map(fn)(any, integer) -> any -> arrayTransform with element and index
.flatMap(fn)(any) -> array -> arrayMap then flatten one level
.filter(fn)(any) -> boolean -> arrayKeep elements where fn returns true
.reject(fn)(any) -> boolean -> arrayRemove elements where fn returns true
.reduce(fn, initial)(acc, el) -> acc, any -> anyAccumulate a single value
.sort()-> arraySort using default order
.sort(fn)(a, b) -> number -> arraySort using a comparator
.sortBy(fn)(any) -> comparable -> arraySort by a key function
.reverse()-> arrayReverse element order
.uniq()-> arrayRemove duplicates
.unique()-> arrayAlias for .uniq()
.uniqBy(fn)(any) -> any -> arrayRemove duplicates by a key function
.uniqueBy(fn)(any) -> any -> arrayAlias for .uniqBy()
.groupBy(fn)(any) -> any -> objectGroup elements by a key function
.chunk(size)integer -> array<array>Split into sub-arrays of given size
.zip(other)array -> array<[any, any]>Pair elements with another array
.flat()-> arrayFlatten one level of nesting
.find(fn)(any) -> boolean -> any | nilFirst element matching fn
.some(fn)(any) -> boolean -> booleanTrue if any element matches fn
.any(fn)(any) -> boolean -> booleanAlias for .some()
.every(fn)(any) -> boolean -> booleanTrue if all elements match fn
.includes(value)any -> booleanTrue if the array contains value
.indexOf(value)any -> integerIndex of first occurrence, -1 if absent
.count(fn)(any) -> boolean -> integerCount elements matching fn
.first()-> any | nilFirst element or nil
.last()-> any | nilLast element or nil
.pop()-> any | nilAlias for .last()
.take(n)integer -> arrayFirst n elements
.drop(n)integer -> arrayAll elements after the first n
.slice(start)integer -> arrayElements from start to end
.slice(start, stop)integer, integer -> arrayElements from start to stop (exclusive)
.at(index)integer -> any | nilElement at index, nil if out of bounds
.sum()-> numberSum of all elements
.min()-> anyMinimum element
.max()-> anyMaximum element
.join(separator)string -> stringJoin elements into a string
.concat(other)array -> arrayConcatenate two arrays
.lengthintegerNumber of elements (property, not a method call)
compute summarize
let active = input.users.filter(u => u.active)
let names = active.map(u => u.name)
let sorted = names.sort()
{count: active.length, names: sorted}

String Methods

Methods available on any string value.

MethodSignatureDescription
.toUpperCase()-> stringConvert to uppercase
.toLowerCase()-> stringConvert to lowercase
.uppercase()-> stringAlias for .toUpperCase()
.lowercase()-> stringAlias for .toLowerCase()
.trim()-> stringRemove leading and trailing whitespace
.trimStart()-> stringRemove leading whitespace only
.trimEnd()-> stringRemove trailing whitespace only
.split(delimiter)string -> array<string>Split into a list on delimiter
.replace(pattern, replacement)string, string -> stringReplace first occurrence
.replaceAll(pattern, replacement)string, string -> stringReplace all occurrences
.startsWith(prefix)string -> booleanTrue if string starts with prefix
.endsWith(suffix)string -> booleanTrue if string ends with suffix
.padStart(length)integer -> stringPad with spaces on the left
.padEnd(length)integer -> stringPad with spaces on the right
.repeat(count)integer -> stringRepeat the string count times
.substring(start)integer -> stringCharacters from start to end
.substring(start, end)integer, integer -> stringCharacters from start to end (exclusive)
.match(pattern)string | regex -> array<string> | nilFirst match, or nil if no match
.matchAll(pattern)string | regex -> array<array<string>>All matches
.test(pattern)string | regex -> booleanTrue if pattern matches
.toString()-> stringIdentity (returns the string itself)
.lengthintegerCharacter count (property, not a method call)
compute format_slug
input.title.toLowerCase().trim().replaceAll(" ", "-")

Global Functions

Global functions are called without a namespace prefix.

Type Checking

FunctionSignatureDescription
typeof(value)any -> stringReturns "number", "string", "boolean", "list", "object", or "null"
isNumber(value)any -> booleanTrue if value is a number
isString(value)any -> booleanTrue if value is a string
isBoolean(value)any -> booleanTrue if value is a boolean
isArray(value)any -> booleanTrue if value is an array
isObject(value)any -> booleanTrue if value is an object
isNull(value)any -> booleanTrue if value is nil
isNaN(value)any -> booleanTrue if value is NaN

Type Conversion

FunctionSignatureDescription
string(value)any -> stringCoerce to string
number(value)string -> integerParse string to integer
parseInt(value)any -> integer | NaNParse to integer, NaN if unparseable
parseFloat(value)any -> float | NaNParse to float, NaN if unparseable

Collection (Polymorphic)

These functions work on both arrays and strings.

FunctionSignatureDescription
length(value)array | string | object -> integerCount of elements, characters, or keys
first(arr)array -> any | nilFirst element or nil
last(arr)array -> any | nilLast element or nil
includes(collection, value)array | string, any -> booleanTrue if collection contains value
indexOf(collection, value)array | string, any -> integerIndex of first occurrence, -1 if absent
slice(collection, start)array | string, integer -> array | stringSub-list or substring from start
slice(collection, start, stop)array | string, integer, integer -> array | stringSub-list or substring from start to stop

Control Flow

FunctionSignatureDescription
while(initial, condition, body)any, (state) -> boolean, (state) -> state -> anyIterate until condition is false. Max 10,000 iterations.
compute collatz
let steps = while(input.n, n => n != 1, n => n % 2 == 0 ? n / 2 : 3 * n + 1)
{result: steps}

Metaprogramming

FunctionSignatureDescription
quote(expr)expr -> FormCapture an expression as a Form at compile time
reflect()-> Form | nilReturn the current machine’s own form

Utilities

FunctionSignatureDescription
inspect(value)any -> stringDebug representation of any value
now()-> stringCurrent UTC time as ISO 8601 (alias for DateTime.now())

Property Access

The .length property works on arrays, strings, and objects without parentheses:

input.items.length // number of elements in an array
input.name.length // number of characters in a string
Object.keys(obj).length // number of keys in an object

Runtime Bindings

Special variables available in machine context:

BindingTypeDescription
meobjectCurrent machine runtime context. Includes the machine name, version, and execution metadata.

See also

  • Expression Language - Operators, literals, destructuring, pattern matching, and control flow
  • compute - The primary step type for expressions
  • decide - Branching logic using expression conditions
  • Field Types - Type system for field declarations