Skip to main content

Function - FunctionBuilder

Function.FunctionBuilder

A FunctionBuilder to build a data transformation in Elara.

Methods on the FunctionBuilder enable you to directly transform data from any number of input

Streams and output any number of return Streams. The body of the function works similarly to most imperative languages (like JavaScript/TypeScript) allowing for definition of temporary variables (with let), reassignment of defined variables (with assign), branching (with if, ifNull and match), loops (with while, forArray, forSet, forDict), as well as logging and raising errors (with log, warn and error). Inside any of these statements you can use East Expressions to access and manipulate data in scope.

A corresponding

Template can be created using .toTemplate().

Example

// Create a function to add two integer streams, equivalent to the Javascript function
//
// function f(a, b) {
// let c = a + b;
// return { c };
// }
//
// f(1n, 2n) == 3n

const a = new SourceBuilder("a").value({ value: 1n })
const b = new SourceBuilder("b").value({ value: 2n })

const f = new FunctionBuilder("f")
.input("a", a.outputStream())
.input("b", b.outputStream())
.body(block => block
.let("c", vars => Add(vars.a, vars.b))
.return({ c: vars => vars.c })
)

Type parameters

NameType
FunctionNameextends string
Inputsextends Record =
RecursiveInputsextends Record =
Functionsextends Record<string, Record> =
MLsextends Record =
Procsextends Record =
Returnsextends null | Record = null

Hierarchy

  • Builder

    FunctionBuilder

Function

constructor

new FunctionBuilder(name, module, inputs, recursiveInputs, defaults, functions, mls, procs, statements, outputs):

FunctionBuilder

Create a FunctionBuilder to build a data tansformation in Elara.

Methods on the FunctionBuilder enable you to directly transform data from any number of input

Streams and output any number of return Streams. The body of the function works similarly to most imperative languages (like JavaScript/TypeScript) allowing for definition of temporary variables (with let), reassignment of defined variables (with assign), branching (with if, ifNull and match), loops (with while, forArray, forSet, forDict), as well as logging and raising errors (with log, warn and error). Inside any of these statements you can use East Expressions to access and manipulate data in scope.

A corresponding

Template can be created using .toTemplate().

Type parameters

NameType
FunctionNameextends string
Inputsextends Record =
RecursiveInputsextends Record =
Functionsextends Record<string, Record> =
MLsextends Record =
Procsextends Record =
Returnsextends null | Record = null

Parameters

NameType
nameFunctionName
moduleModulePath
inputsRecord
recursiveInputsRecord
defaultsRecord
functionsFunctions
mlsMLs
procsProcs
statementsnull | FunctionStatement[]
outputsnull | Record

Returns

FunctionBuilder

Example

// Create a function to add two integer streams, equivalent to the Javascript function
//
// function f(a, b) {
// let c = a + b;
// return { c };
// }
//
// f(1n, 2n) == 3n

const a = new SourceBuilder("a").value({ value: 1n })
const b = new SourceBuilder("b").value({ value: 2n })

const f = new FunctionBuilder("f")
.input("a", a.outputStream())
.input("b", b.outputStream())
.body(block => block
.let("c", vars => Add(vars.a, vars.b))
.return({ c: vars => vars.c })
)

Overrides

Builder.constructor


body

body(body):

FunctionBuilder<FunctionName, Inputs, RecursiveInputs, Functions, MLs, Procs, GetReturns<ReturnType>>

Define the "body" of this function, where computations are performed on inputs and outputs are returned. The body can be thought of as a block of code containing statements like let and return, or even nested blocks of code (using if or while). This code is executed much like the body of a function in imperative languages, like JavaScript/TypeScript.

To use this method, an empty "block" of code is injected on which you can use define statements using the builder pattern (or fluent code pattern) and return the result.

Type parameters

NameType
Bextends (block: BlockBuilder<{ [K in string | number | symbol]: Variable } & { [K in string | number | symbol]: Variable }, { [K in string | number | symbol]: { [I in string | number | symbol]: Functions[K][I]["type"] } }, MLs, Procs, null>) => TerminalBlockBuilder<null | Record>

Parameters

NameType
bodyB

Returns

FunctionBuilder<FunctionName, Inputs, RecursiveInputs, Functions, MLs, Procs, GetReturns<ReturnType>>

Example

// Create a function to add two integer streams, equivalent to the Javascript function
//
// function f(a, b) {
// let c = a + b;
// return { c };
// }
//
// f(1n, 2n) == 3n

const a = new SourceBuilder("a").value({ value: 1n })
const b = new SourceBuilder("b").value({ value: 2n })

const f = new FunctionBuilder("f")
.input("a", a.outputStream())
.input("b", b.outputStream())
.body(block => block
.let("c", vars => Add(vars.a, vars.b))
.return({ c: vars => vars.c })
)

input

input(name, stream):

FunctionBuilder<FunctionName, Inputs & { [K in string]: T }, RecursiveInputs, Functions, MLs, Procs, Returns>

Define an input streams as an input parameter of function. Each input stream is given a variable name that is accessible in the body of the function.

Type parameters

NameType
Nameextends string
Textends EastType

Parameters

NameType
nameName
streamStream

Returns

FunctionBuilder<FunctionName, Inputs & { [K in string]: T }, RecursiveInputs, Functions, MLs, Procs, Returns>

Example

// Create a function to add two integer streams, equivalent to the Javascript function
//
// function f(a, b) {
// let c = a + b;
// return { c };
// }
//
// f(1n, 2n) == 3n

const a = new SourceBuilder("a").value({ value: 1n })
const b = new SourceBuilder("b").value({ value: 2n })

const f = new FunctionBuilder("f")
.input("a", a.outputStream())
.input("b", b.outputStream())
.body(block => block
.let("c", vars => Add(vars.a, vars.b))
.return({ c: vars => vars.c })
)

ml

ml(ml):

FunctionBuilder<FunctionName, Inputs, RecursiveInputs, Functions, MLs & { [K in string]: MLDescription<StructType, T> }, Procs, Returns>

Include a machine-learning function that can evaluated inside the expressions of this FunctionBuilder.

Type parameters

NameType
MLNameextends string
Featuresextends Record
Textends EastType

Parameters

NameTypeDescription
mlAbstractMLBuilderthe MLModelBuilder model add to the FunctionBuilder

Returns

FunctionBuilder<FunctionName, Inputs, RecursiveInputs, Functions, MLs & { [K in string]: MLDescription<StructType, T> }, Procs, Returns>

Example

 // create an ml function
const my_ml_function = new MLModelBuilder("my_ml_function")
.feature("feature1", FloatType)
.feature("feature2", StringType)
.output(FloatType)

// create the predict_amount function
const feature1 = new SourceBuilder("feature1").value({ value: 3.14 })
const feature2 = new SourceBuilder("feature2").value({ value: "abc" })

const f = new FunctionBuilder("f")
.input("feature1", feature1.outputStream())
.input("feature2", feature2.outputStream())
.ml(my_ml_function)
.body(block => block
.let("output", (vars, mls) => mls.my_ml_function(Struct({ feature1: vars.feature1, feature2: vars.feature2 })))
.return({ output: vars => vars.output })
)

outputStreams

outputStreams(): Returns extends Record ? { [K in string | number | symbol]: Stream } :

Return the output streams for this function.

Returns

Returns extends Record ? { [K in string | number | symbol]: Stream } :

Example

// Create a function to add two integer streams, equivalent to the Javascript function
//
// function f(a, b) {
// let c = a + b;
// return { c };
// }
//
// f(1n, 2n) == 3n

const a = new SourceBuilder("a").value({ value: 1n })
const b = new SourceBuilder("b").value({ value: 2n })

const f = new FunctionBuilder("f")
.input("a", a.outputStream())
.input("b", b.outputStream())
.body(block => block
.let("c", vars => Add(vars.a, vars.b))
.return({ c: vars => vars.c })
)

const c_stream = f.outputStreams().c

procedure

procedure(procedure):

FunctionBuilder<FunctionName, Inputs, RecursiveInputs, Functions, MLs, Procs & { [K in string]: ProcedureDescription<ProcName, StructType, T> }, Returns>

Include a procedure that can evaluated inside the expressions of this FunctionBuilder.

Type parameters

NameType
ProcNameextends string
ProcInputsextends Record
Textends EastType

Parameters

NameTypeDescription
procedureProcedureFinalizerthe Procedure to add to the FunctionBuilder

Returns

FunctionBuilder<FunctionName, Inputs, RecursiveInputs, Functions, MLs, Procs & { [K in string]: ProcedureDescription<ProcName, StructType, T> }, Returns>

Example

 // create a procedure to multiply two numbers
const my_procedure = new Procedure("my_procedure")
.input("x", FloatType)
.input("y", FloatType)
.output(FloatType)
.body(b => b
.return(vars => Multiply(vars.x, vars.y))
);

// create the predict_amount function
const x = new SourceBuilder("x").value({ value: 3.14 });
const y = new SourceBuilder("y").value({ value: 42.0 });

const f = new FunctionBuilder("f")
.input("x", x.outputStream())
.input("y", y.outputStream())
.procedure(my_procedure)
.body(block => block
.let("output", (vars, procs) => procs.my_procedure(Struct({ x: vars.x, y: vars.y })))
.return({ output: vars => vars.output })
);

toTemplate

toTemplate(): Object

Return the template elements for this function.

Returns

Object

NameType
streamsRecord
tasks

Example

// Create a function to add two integer streams, equivalent to the Javascript function
//
// function f(a, b) {
// let c = a + b;
// return { c };
// }
//
// f(1n, 2n) == 3n

const a = new SourceBuilder("a").value({ value: 1n })
const b = new SourceBuilder("b").value({ value: 2n })

const f = new FunctionBuilder("f")
.input("a", a.outputStream())
.input("b", b.outputStream())
.body(block => block
.let("c", vars => Add(vars.a, vars.b))
.return({ c: vars => vars.c })
)

export default f.toTemplate()

Overrides

Builder.toTemplate

Other

function

function(f):

FunctionBuilder<FunctionName, Inputs, RecursiveInputs, Functions & { [K in string]: { [I in string | number | symbol]: Stream } }, MLs, Procs, Returns>

Elara functions can be defined recursively using optional input and output streams. This method declares another function that can be called as a result of this function, where "calling" the function implies providing the optional input values defined by recursiveInput.

Note that this interface is experimental and not recommended for usage at this time. It is up to the user to ensure termination and avoid infinite recursion and excessive usage of the Elara cluster.

Type parameters

NameType
Nameextends string
Rextends Record
Fextends FunctionBuilder<Name, Record, R, , , , null>

Parameters

NameType
fF

Returns

FunctionBuilder<FunctionName, Inputs, RecursiveInputs, Functions & { [K in string]: { [I in string | number | symbol]: Stream } }, MLs, Procs, Returns>


recursiveInput

recursiveInput(name, initial_value):

FunctionBuilder<FunctionName, Inputs, RecursiveInputs & { [K in string]: ReturnType["type"] }, Functions & { [K in string]: { [I in string | number | symbol]: Stream } & { [K in string]: Stream<ReturnType["type"]> } }, MLs, Procs, Returns>

Elara functions can be defined recursively using optional input and output streams. This method defines an "optional" inputs that have an initial default value, and can be provided recurssively by this or downstream functions.

Note that this interface is experimental and not recommended for usage at this time. It is up to the user to ensure termination and avoid infinite recursion and excessive usage of the Elara cluster.

Type parameters

NameType
Nameextends string
Fextends (p: { [K in string | number | symbol]: Variable }) => EastFunction

Parameters

NameType
nameName
initial_valueF

Returns

FunctionBuilder<FunctionName, Inputs, RecursiveInputs & { [K in string]: ReturnType["type"] }, Functions & { [K in string]: { [I in string | number | symbol]: Stream } & { [K in string]: Stream<ReturnType["type"]> } }, MLs, Procs, Returns>


recursiveInputStreams

recursiveInputStreams(): { [K in string | number | symbol]: Stream }

Elara functions can be defined recursively using optional input and output streams. This method returns the input streams defined via recursiveInput, which are written to when a function terminates with the recurse method.

Note that this interface is experimental and not recommended for usage at this time. It is up to the user to ensure termination and avoid infinite recursion and excessive usage of the Elara cluster.

Returns

{ [K in string | number | symbol]: Stream }