Whistle built-in functions

This page contains a list of the available functions in the Whistle runtime shipped with Manufacturing Data Engine (MDE).

Import

The builtins package does not need to be imported, or prefixed in front of any functions. These functions are available everywhere.

Functions

This section outlines the functions available.

and

and(args: Closure...) returns Primitive

Arguments

args: Closure...

Description

Return true iff all arguments are truthy. It stops evaluating once it encounters a falsey. argument.

arrayOf

arrayOf(items: Data...) returns Array

Arguments

items: Data...

Description

Creates a new Array from the given items.

base64decode

base64decode(base64: String) returns Primitive

Arguments

base64: String - The base64 to encode. If decoding structured data, use deserializeJson after this.

Description

Decodes the given String from base64. The base64 encoding is expected to contain a UTF-8 string.

An empty string or null input will return an empty string. An empty string or null input will return an empty string.

For example:

  simple: base64decode("dGhpcyBpcyBhIHN0cmluZw==") // simple == "this is a string"
  structure: deserializeJson(
              base64decode("eyJhcnJheSI6WzEsMiwzXSwibmVzdGVkIjp7Im51bSI6MzIxfSwibnVtIjoxMjN9"))
  // structure == {
      array: [1, 2, 3]
      num: 123
      nested: {
          num: 321
      }
  }

base64encode

base64encode(data: String) returns Primitive

Arguments

data: String - The string to encode. If encoding structured data, use serializeJson first.

Description

Encodes the given String to base64, by first encoding it to UTF-8 bytes.

An empty string or null input will return an empty string.

For example:

simple: base64encode("this is a string") // simple == "dGhpcyBpcyBhIHN0cmluZw=="

var structure: {
    array: [1, 2, 3]
    num: 123
    nested: {
        num: 321
    }
}

structure_enc: base64encode(serializeJson(structure))
// structure_enc == "eyJhcnJheSI6WzEsMiwzXSwibmVzdGVkIjp7Im51bSI6MzIxfSwibnVtIjoxMjN9"

calculateElapsedDuration

calculateElapsedDuration(iso8601StartDateTime: String, iso8601EndDateTime: String, timeScale: String) returns Primitive - Primitive

Arguments

iso8601StartDateTime: String - timestamp in ISO 8601 format (yyyy-MM-dd'T'HH:mm:ss.SSSZ).

iso8601EndDateTime: String - timestamp in ISO 8601 format (yyyy-MM-dd'T'HH:mm:ss.SSSZ).

timeScale: String - String representing the time scale to represent the difference between the two points in time. Supported time scales - YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS, MILLIS.

Description

Calculates the duration between two points in time by converting ISO 6801 formatted timestamps to millisecond values, subtracting the start from the end value and dividing that results by the number of milliseconds in the provided time scale.

Throws

  • IllegalArgumentException - if either ISO 8601 formatted input values are improperly formatted or if an unsupported time scale is passed in to the method.

calculateNewDateTime

calculateNewDateTime(iso8601DateTime: String, value: Long, timeScale: String) returns Primitive - Primitive

Arguments

iso8601DateTime: String - timestamp in ISO 8601, format(yyyy-MM-dd'T'HH:mm:ss.SSSZ).

value: Long - value to add to the timestamp

timeScale: String - String representing the time scale to which the value should be added. Supported time scales - YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS, MILLIS

Description

Adds or subtracts a specific value associated with a time scale to the input ISO 8601 formatted timestamp (add if value is positive, subtracts if value is negative) and returns a new ISO 8601 formatted timestamp as a Primitive (string).

Throws

  • IllegalArgumentException - if the ISO 8601 formatted input value is improperly formatted, the value is negative, or if an unsupported time scale is passed in to the method.

callFn

callFn(functionName: String, args: Data...) returns Data - Data the result of the function call.

Arguments

functionName: String - String the name of the function to call.

args: Data... - Data the arguments to the function.

Description

Uses reflection to call the function String with the functionName String and passes the Data arguments as arguments to the function. The function must reside in the same package where the call method is invoked.

callPackageFn

callPackageFn(packageName: String, functionName: String, args: Data...) returns Data - Data the result of the function call.

Arguments

packageName: String - String the package where the function resides.

functionName: String - String the name of the function to call.

args: Data... - Data the arguments to the function.

Description

Uses reflection to call the function String with the functionName String within the packageName and passes the Data arguments as arguments to the function.

currentTime

currentTime(format: String) returns Primitive - Primitive string holding a representation of the current timestamp in the given format.

Arguments

format: String - format String for current timestamp.

Description

Gets the current timestamp in the provided Joda Time format string (https://www.joda.org/joda-time/key_format.html).

deepCopy

deepCopy(data: Data) returns Data

Arguments

data: Data

Description

Returns a deep copy of the input Data.

deserializeJson

deserializeJson(json: String) returns Data - The deserialized Whistle Data.

Arguments

json: String - The JSON string to deserialize.

Description

Deserializes the JSON string to the Whistle Data format.

div

div(dividend: Primitive, divisor: Primitive) returns Primitive

Arguments

dividend: Primitive

divisor: Primitive

Description

Divides dividend by divisor. Throws IllegalArgumentException if one ore more are not numbers. Nulls become 0.

eq

eq(first: Data, rest: Data...) returns Primitive

Arguments

first: Data

rest: Data...

Description

Returns true iff all parameters are equal.

explicitEmptyString

explicitEmptyString() returns Primitive

Arguments

Description

Allows a user to explicitly output an empty string as a value for fields.

For example:

thisWillOutput: explicitEmptyString()
thisWillNotOutput: ""

extractRegex

extractRegex(input: String, pattern: String) returns Primitive - the first match of pattern in input. NullData if either input or pattern is null or there is no match.

Arguments

input: String - string input to match.

pattern: String - string regex pattern.

Description

Returns the substring in input that first matches pattern, or null if there's no match for pattern in input.

extractRegex

extractRegex(input: String, pattern: String, formatter: Closure) returns Array - An array where each element is the result of calling formatter on each match.

Arguments

input: String - The input string to match against.

pattern: String - The regex pattern to match.

formatter: Closure - A closure with free variable $, where $ is a container with a field for each group, as in $.0 containing the whole match (group 0), $.1 containing group 1 (if it exists in the pattern), etc.

Description

Finds all matches of the given regex pattern in the given input, and passes each match to the given formatter. Returns a result of the formatters in an array.

The parameter passed to formatter - $ - contains each group from the regex as a field. That is, group 0 (the whole match) is $.0, group 1 is $.1, etc. Groups are not accessible by name.

Example:

var pattern: "a(b+)(c+)d"
var input: "abbcccd______abbbbccccccd"

extractRegex(input, pattern, $.1) == ["bb", "bbbb"]
extractRegex(input, pattern, $.2) == ["ccc", "cccccc"]
extractRegex(input, pattern, {
  whole: $.0
  bees: $.1
  cees: $.2
}) == [
  {
    bees: "bb",
    cees: "ccc",
    whole: "abbcccd"
  },
  {
    bees: "bbbb",
    cees: "cccccc",
    whole: "abbbbccccccd"
  }
]

fail

fail(message: String) returns NullData

Arguments

message: String

Description

Throws an exception with the given message. It will be caught by Errors#withError if present.

fields

fields(container: Container) returns Array

Arguments

container: Container

Description

Returns an array of the fields in the given container. The fields are sorted alphabetically.

fileExists

fileExists(path: String) returns Primitive

Arguments

path: String - The path to the resource. Relative paths are resolved relative to the current file. This path can use the same loaders or schemes as imports (e.x. file:///hello/world or gs://my-bucket/hello/world if a _gcpname plugin is imported).

Description

Returns true iff the file at the given path exists (regardless of whether it is empty).

fileName

fileName(path: String) returns Primitive

Arguments

path: String

Description

Returns the file or dir name specified by the given path (including extension). This returns the last path segment after the last /. If there are query parameters or other suffixes after this segment, they are included.

For example:

fileName("hello") == "hello"
fileName("/hello") == "hello"
fileName("/hello/") == fileName("") == ""
fileName("/hello/world/this/is/a/path.json.zip.tar.gz") == "path.json.zip.tar.gz"

floor

floor(data: Data) returns Primitive

Arguments

data: Data

Description

Returns the Math.floor() value of a numeric Primitive. Throws an exception if the input value is not numeric.

formatDateTime

formatDateTime(format: String, iso8601DateTime: String) returns Primitive - Primitive string holding a representation of the provided timestamp formatted according to the given format; NullData.instance if input datetime is not valid as ISO 8601.

Arguments

format: String - String indicating the destination format of the given timestamp.

iso8601DateTime: String - a timestamp in ISO 8601 format.

Description

Parses the given timestamp (which must be in ISO 8601 - https://www.w3.org/TR/NOTE-datetime, yyyy-MM-dd'T'HH:mm:ss.SSSZ format), and reformats it according to the given format (forcing a UTC timezone). The given format must be specified according to Java formatting rules: https://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html

formatDateTimeZ

formatDateTimeZ(format: String, timezone: String, iso8601DateTime: String) returns Primitive - Primitive string holding a representation of the provided timestamp formatted according to the given format; NullData.instance if input datetime is not valid as ISO 8601.

Arguments

format: String - String indicating the destination format of the given timestamp.

timezone: String - String describing a timezone either by id like "America/Toronto" or by offset like "+08:00".

iso8601DateTime: String - a timestamp in ISO 8601 format.

Description

Parses the given timestamp (which must be in ISO 8601 - https://www.w3.org/TR/NOTE-datetime, yyyy-MM-dd'T'HH:mm:ss.SSSZ format), and reformats it according to the given format with the given timezone. The given format must be specified according to Java formatting rules: https://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html

get

get(source: Data, path: String) returns Data

Arguments

source: Data

path: String

Description

Gets the value at the given path applied to the given value.

getEpochMillis

getEpochMillis(iso8601DateTime: String) returns Primitive - Primitive double of the milliseconds since the Unix epoch for the provided datetime or NullData if parse of timestamp using the ISO 8601 format fails.

Arguments

iso8601DateTime: String - a timestamp in ISO 8601 format (yyyy-MM-dd'T'HH:mm:ss.SSSZ).

Description

Gets the milliseconds from the Java epoch of 1970-01-01T00:00:00Z for the provided datetime, which must be in ISO 8601 (https://www.w3.org/TR/NOTE-datetime) format.

groupBy

groupBy(array: Array, keyExtractor: Closure) returns Array

Arguments

array: Array

keyExtractor: Closure

Description

Groups the elements of an array by their keys extracted by the keyExtractor closure. The output is an array of objects/containers, each with two fields "key" and "value", analogous to key:value pairs. The "key" field of each container in the return value is a unique join key in the original collection computed by the keyExtractor closure. The "value" field will be a collection of elements from the original collection that maps to the join key in the "key" field. Example:

var array: [{num: 1; word: "one";}, {num: 2; word: "two";},
             {num: 3; word: "three";}, {num: 4; word: "four";}]
 var groupByResult: array[groupBy if $.num > 2 then "biggerThan2" else $.num + 2]
 // groupByResult == [{key: "biggerThan2"; elements: [{num: 3; word: "three";},
 //                                                   {num: 4; word: "four";}];},
 //                   {key: 3; elements: [{num: 1; word: "one";}];},
 //                   {key: 4; elements: [{num: 2; word: "two";}];}
 //                   ]

gt

gt(left: Primitive, right: Primitive) returns Primitive

Arguments

left: Primitive

right: Primitive

Description

Returns true iff the left parameter if greater than the right parameter. Throws IllegalArgumentException either argument is not a number. Null becomes 0.

gtEq

gtEq(left: Primitive, right: Primitive) returns Primitive

Arguments

left: Primitive

right: Primitive

Description

Returns true iff the left parameter if greater than or equal to the right parameter. Throws IllegalArgumentException either argument is not a number. Null becomes 0.

hash

hash(obj: Data) returns Primitive - Primitive String hash code representing the input Data object.

Arguments

obj: Data - Data object to generate hash code for.

Description

Generates a Primitive String hash from the given Data object. Key order is not considered for Containers, (Array item order is). This is not cryptographically secure and is not to be used for secure hashing. Uses murmur3 hashing for speed and stability.

intHash

intHash(obj: Data) returns Primitive - Primitive holding Integer hash code representing the input Data object.

Arguments

obj: Data - Data object to generate hash code for.

Description

Generates an Integer hash from the given Data object. Key order is not considered for Containers, (Array item order is). This is not cryptographically secure and is not to be used for secure hashing. Uses murmur3 hashing for speed and stability.

is

is(data: Data, type: String) returns Primitive

Arguments

data: Data

type: String

Description

Returns true if the given data is of the given type (according to #types).

Possible basic types are: Array, Container, Primitive, Dataset, and null. Implementations, like DefaultArray can vary depending on the execution environment.

This check is not sensitive to letter casing.

isDateTimeBetween

isDateTimeBetween(iso8601StartDateTime: String, iso8601EndDateTime: String, iso8601CompareDateTime: String) returns Primitive - Primitive boolean value true if inside window, false otherwise.

Arguments

iso8601StartDateTime: String - timestamp in ISO 8601 format (yyyy-MM-dd'T'HH:mm:ss.SSSZ)

iso8601EndDateTime: String - timestamp in ISO 8601 format (yyyy-MM-dd'T'HH:mm:ss.SSSZ)

iso8601CompareDateTime: String - timestamp in ISO 8601 format (yyyy-MM-dd'T'HH:mm:ss.SSSZ)

Description

Calculates whether the value specified by iso8601CompareDateTime exists within the window defined by iso8601StartDateTime and iso8601EndDateTime. All ISO 8601 timestamps are converted to millisecond values and a comparison is done inclusive of the start and end points.

Throws

  • IllegalArgumentException - if any of ISO 8601 formatted input values are improperly formatted.

isNil

isNil(data: Data) returns Primitive

Arguments

data: Data

Description

Returns true iff the given data is null or empty.

isNotNil

isNotNil(data: Data) returns Primitive

Arguments

data: Data

Description

Returns true iff the given primitive is not null or empty depending on its own implementation.

iterate

iterate(closure: Closure, iterables: NullData...) returns NullData

Arguments

closure: Closure

iterables: NullData...

Description

Iteration stub for iterating over NullData, to disambiguate it from a dataset or an array. This method always returns NullData and never calls the given closure.

iterate

iterate(closure: Closure, iterables: Array...) returns Array

Arguments

closure: Closure - The closure to use for iteration.

iterables: Array... - The arrays to iterate.

Description

Iterate the given Array(s) together passing them one element at a time to the given closure, and composing the results into a new array. The closure must therefore have the same number of free arguments as there are arrays to iterate together.

If multiple arrays are iterated together, then zipped iteration is performed. This means that for every index, an element is selected at that index from each iterated array (except empty arrays, where null is selected for every index). These elements are passed in as arguments to the function (in place of the arrays), and the results of the function are composed to the returned new Array. All non-empty arrays must have the same sizes (empty Arrays just yield as many nulls as necessary).

For example, if (a, b, c, x, y) are args, a and b are arrays of size 3, c is an array of size 0 (empty) and x and y are non-iterated args (that is, they are not free args), then the given function will be called like:

-   fn(a[0], b[0], null, x, y)
-   fn(a[1], b[1], null, x, y)
-   fn(a[2], b[2], null, x, y)

The results of these calls will be collected into an array of length 3.

This method may also be called directly, with an anonymous expression. For example: iterate($1 + $2, ["a", "b", "c"], ["A", "B", "C"]) will return ["aA", "bB", "cC"]. Alternatively, iterate($ + 100, [1, 2, 3]) will return [101, 102, 103]. As many arguments as selected may be passed in, and will be bound to $1, $2, $3...$n in order. If there is only one array argument, it is bound to just $ (with no number).

iterate

iterate(closure: Closure, iterables: Container...) returns Container

Arguments

closure: Closure - The closure to use for iteration.

iterables: Container... - The containers to iterate.

Description

Containers are iterated by passing in the values of each key. The resulting value is then assigned to the corresponding key in the output container.

The main notable difference between arrays and containers is that there is no size requirement for containers - since the iteration is done upon key-values, containers that are missing the key just get a Null value.

For example, if (a, b, c, x, y) are args, a, b, and c are containers such that a = {k1: ..., k3: ...} and b = {k1: ..., k2: ...} and c = {}, then the given function will be called like:

-   fn(a.k1, b.k1, c.k1, x, y)
-   fn(a.k2, b.k2, c.k2, x, y)
-   fn(a.k3, b.k3, c.k3, x, y)

where a.k2 == b.k3 == c.k1 == c.k2 == c.k3 == null

The results of these calls will be collected into a container as in:

{
   k1: fn(a.k1, b.k1, c.k1, x, y)
   k2: fn(a.k2, b.k2, c.k2, x, y)
   k3: fn(a.k3, b.k3, c.k3, x, y)
}

Example:

var c1: {
  k1: "c1k1"
  k2: "c1k2"
}

def modify(value) value + "-modified"

modify(c1[]) == {
  "k1": "c1k1-modified",
  "k2": "c1k2-modified"
}

var c2: {
  k1: "c2k1"
  k3: "c2k3"
}

var c3: {
  k1: "c3k1"
  k3: "c3k3"
}

sum(c1[], c2[], c3[]) == {
  "k1": "c1k1c2k1c3k1",
  "k2": "c1k2",
  "k3": "c2k3c3k3"
}

iterate

iterate(closure: Closure, dataset: Dataset) returns Dataset

Arguments

closure: Closure - The closure to use for iteration.

dataset: Dataset - The dataset to iterate/map.

Description

Iterates a dataset through the given closure. Each dataset element will be passed through the given closure using the dataset's Dataset#map(RuntimeContext, Closure, boolean) implementation.

join

join(left: Array, right: Array, joinOp: Closure) returns Array - Array of joined elements. Joined pairs are themselves arrays, with matching elements from left and right, or nulls in place of no matches.

Arguments

left: Array - The left array

right: Array - The right array

joinOp: Closure - a predicate operating on $left and $right, which returns true if the two elements must be joined together.

Description

Performs a full outer join on the two given arrays.

Example:

var array1: [{
  id: 1
  val: "1aaa"
}, {
  id: 2
  val: "1bbb"
}]
var array2: [{
  id: 1
  val: "2aaa"
}, {
  id: 3
  val: "2ccc"
}]

join(array1, array2, $left.id == $right.id) == [
 [{ id: 1; val: "1aaa"; }, { id: 1; val: "2aaa"; }],
 [{ id: 2; val: "1bbb"; }, {}],
 [{}, { id: 3; val: "2ccc"; }]
]

Ordering: Order is preserved such that:

  • Items from left (and corresponding matches from right, if any) appear first
  • Unmatched remaining items from right appear last

Duplicate items: Duplicate items are only matched once. That is, if left is Al Al Bl, and right is Ar Br Br Cr, the result is

Al - Ar
Al - null
Bl - Br
null - Br
null - Cr

joinPath

joinPath(first: String, rest: String...) returns Primitive

Arguments

first: String - The first element of the path.

rest: String... - The remaining elements of the path.

Description

Joins the given path segments, then returns the normalized path. Normalized means all redundant relative segments such as non-leading ./ and ../ are resolved away.

Example:

joinPath("./one/../two", "three") == "./two/three"
joinPath("../one/../two", "three", "four") == "../two/three/four"
joinPath("/one/two", "../three") == "/one/three"
joinPath("one/two", "three") == "one/two/three"
joinPath("hello:///bucket/one/two", "../three", "four") == "hello:///bucket/one/three/four"

last

last(array: Array) returns Data

Arguments

array: Array

Description

Returns the lastIndex data Data in a given Array or Null data for an empty array

listFiles

listFiles(pattern: String) returns Array

Arguments

pattern: String - A file pattern to match against, in glob form. Only local files are supported. For more info on glob syntax, see getPathMatcher("glob")

Description

Lists all files matching the given pattern. Relative paths are resolved against the current file.

Example:

Given directories:
/
├── current.wstl <------ we are in this file.
├── aaa.json
├── one
│     ├── bar
│     │     ├── fff.json
│     │     └── ggg.json
│     ├── bbb.zzz.json
│     └── foo
│         ├── ccc.json
│         ├── ddd.json
│         └── eee.zzz.json
└── two
    ├── hhh.zzz.json
    └── iii.json

listFiles("./*.json") == ["aaa.json"]
listFiles("./**/*.json") == ["/one/bar/ggg.json", "/one/foo/ccc.json",
          "/one/foo/eee.zzz.json", "/two/iii.json", "/one/bar/fff.json", "/one/bbb.zzz.json",
          "/one/foo/ddd.json", "/two/hhh.zzz.json"]
listFiles("/**/*.zz?.json") == ["./one/bbb.zzz.json", "./one/foo/eee.zzz.json",
                                 "./two/hhh.zzz.json"]

listLen

listLen(array: Array) returns Primitive

Arguments

array: Array

Description

Returns the length of the given Array.

loadJson

loadJson(path: String) returns Data

Arguments

path: String - The path to the resource. Relative paths are resolved relative to the current file. This path can use the same loaders or schemes as imports (e.x. file:///hello/world or gs://my-bucket/hello/world if a _gcpname plugin is imported).

Description

Loads the json data at the given path, and returns it as a Data.

loadText

loadText(path: String) returns Primitive

Arguments

path: String - The path to the resource. Relative paths are resolved relative to the current file. This path can use the same loaders ot schemes as imports (e.x. file:///hello/world or gs://my-bucket/hello/world if a _gcpname plugin is imported).

Description

Loads the UTF-8 text data at the given path, and returns it as a string primitive.

lt

lt(left: Primitive, right: Primitive) returns Primitive

Arguments

left: Primitive

right: Primitive

Description

Returns true iff the left parameter if less than the right parameter. Throws IllegalArgumentException either argument is not a number. Null becomes 0.

ltEq

ltEq(left: Primitive, right: Primitive) returns Primitive

Arguments

left: Primitive

right: Primitive

Description

Returns true iff the left parameter if less than or equal to the right parameter. Throws IllegalArgumentException either argument is not a number. Null becomes 0.

matchesRegex

matchesRegex(str: String, regex: String) returns Primitive - Primitive boolean, true iff input string matches input regex pattern

Arguments

str: String - Primitive string input to match.

regex: String - Primitive string regex pattern.

Description

Returns true iff the Primitive string matches the Primitive string regex pattern.

mul

mul(first: Primitive, rest: Primitive...) returns Primitive

Arguments

first: Primitive

rest: Primitive...

Description

Multiplies all parameters together. Throws IllegalArgumentException if one or more are not numbers. Nulls become 0.

neq

neq(first: Data, rest: Data...) returns Primitive

Arguments

first: Data

rest: Data...

Description

Returns true iff any two parameters are not equal.

not

not(data: Data) returns Primitive

Arguments

data: Data

Description

If the given data represents a boolean primitive, returns true iff the boolean value is false. Otherwise returns true iff the data is null or empty.

or

or(args: Closure...) returns Primitive

Arguments

args: Closure...

Description

Returns true iff any of the arguments are truthy. It stops evaluating once it encounters a truthy. argument.

parseDateTime

parseDateTime(format: String, datetime: String) returns Primitive - Primitive string holding an ISO 8601 representation of the provided timestamp; NullData.instance if parse of timestamp using provided format fails.

Arguments

format: String - format String for parsing the provided timestamp.

datetime: String - timestamp String to be parsed.

Description

Parses String timestamp into the ISO 8601 "Complete date plus hours, minutes, seconds and a decimal fraction of a second" format, in the UTC timezone (https://www.w3.org/TR/NOTE-datetime, yyyy-MM-dd'T'HH:mm:ss.SSSZ) from the format specified according to Java formatting rules: https://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html

Missing components are defaulted, except literals which are non-optional.

parseEpochMillis

parseEpochMillis(input: Long) returns Primitive - Primitive String of a timestamp in ISO 8601 format (yyyy-MM-dd'T'HH:mm:ss.SSSZ) or NullData if parse fails.

Arguments

input: Long - the number of milliseconds from 1970-01-01T00:00:00Z.

Description

Gets the Java epoch of 1970-01-01T00:00:00Z from the milliseconds for the provided datetime.

parseNum

parseNum(str: String) returns Primitive

Arguments

str: String

Description

Parses String and returns Primitive double.

range

range(start: Primitive, end: Primitive) returns Array

Arguments

start: Primitive

end: Primitive

Description

Returns an array of sequentially ordered integers from start (inclusive) to end (exclusive) by an increment step of 1. Example:

var x : range(5, 10) // x: [5, 6, 7, 8, 9]

range

range(size: Primitive) returns Array

Arguments

size: Primitive

Description

Returns an array of sequentially ordered integers with provided size starting from 0 and incremented in steps of 1. Example:

var x : range(5) // x: [0, 1, 2, 3, 4]

reduce

reduce(array: Array, seed: Data, accumulator: Closure) returns Data - Data representing the result of the reduction.

Arguments

array: Array - Array to reduce.

seed: Data - Initial value of $acc.

accumulator: Closure - Closure to use as the accumulation function. $acc represents the cumulative reduced value so far, and $cur represents the current value to accumulate. The result of this closure is the next $acc.

Description

Performs a reduction on the elements of an Array using an associative accumulation Closure. If the array is empty, the given seed is returned.

Example:

reduce([1, 2, 3], 10, $acc + $cur) == 16
reduce([1], 10, $acc + $cur) == 11
reduce([1], 10, "some const") == "some const"

reduce

reduce(array: Array, accumulator: Closure) returns Data - Data representing the result of the reduction.

Arguments

array: Array - Array to reduce.

accumulator: Closure - Closure to use as the accumulation function. $acc represents the cumulative reduced value so far, and $cur represents the current value to accumulate. The result of this closure is the next $acc.

Description

Performs a reduction on the elements of an Array using an associative accumulation Closure. If the array is empty, null data is returned. If the array has only one item, that item is returned.

Example:

reduce([1, 2, 3], $acc + $cur) == 6
reduce([1], $acc + $cur) == 1
reduce([1], "some const") == 1

serializeJson

serializeJson(data: Data) returns Primitive - A string representing the JSON serialization of the input data.

Arguments

data: Data - The data to serialize.

Description

Serializes the Data input to JSON string.

sortBy

sortBy(array: Array, keySelector: Closure) returns Array - sorted Array.

Arguments

array: Array - Array to sort.

keySelector: Closure - Closure to use for extracting sortBy key.

Description

Sorts an Array using the key specified by the provided Closure.

sortByDescending

sortByDescending(array: Array, keySelector: Closure) returns Array - Array sorted in descending order.

Arguments

array: Array - Array to sort.

keySelector: Closure - Closure to use for extracting sort-by key.

Description

Sorts an Array in descending order using the key specified by the provided Closure.

split

split(str: String, delimiter: String) returns Array - Array of substrings of the input String which are partitioned by the provided delimiter.

Arguments

str: String - String to split.

delimiter: String - String to use to split the input string.

Description

Splits a string using the provided delimiter. Does not trim empty strings or trailing whitespace characters. When the delimiter is null or empty, returns an array of individual characters.

split

split(str: String) returns Array - Array of individual characters in the input string.

Arguments

str: String - string to split.

Description

Splits the String str into individual characters.

strFmt

strFmt(format: String, args: Data...) returns Primitive

Arguments

format: String - A format string, using String#format(String, Object...) conventions.

args: Data... - Arguments to fill into the placeholders.

Description

Formats a string using the given format and arguments.

strJoin

strJoin(delimiter: String, components: Array) returns Primitive - the join result as a string Primitive.

Arguments

delimiter: String - String to use to join the given array

components: Array - Array of data to join.

Description

Joins the given Array using the delimiter. The array is cast to its string expression.

sub

sub(first: Primitive, rest: Primitive...) returns Primitive

Arguments

first: Primitive

rest: Primitive...

Description

Subtract the rest of parameters from the first. Throws IllegalArgumentException if one or more are not numbers. Nulls become 0.

sum

sum(first: Primitive, rest: Primitive...) returns Primitive

Arguments

first: Primitive

rest: Primitive...

Description

Returns true the sum of all the parameters. If they are numbers they are added; Strings are concatenated. If there is a mix of types, and any are strings, all are treated as strings (e.x. true + 1 + "hello" = "true1hello". If there is a mix of types and none are strings (or all are boolean) an error is raised.

toLower

toLower(str: String) returns Primitive

Arguments

str: String

Description

Converts all letters in the provided string to lowercase.

toUpper

toUpper(str: String) returns Primitive

Arguments

str: String

Description

Converts all letters in the provided string to uppercase.

tryParseNum

tryParseNum(primitive: Primitive) returns Primitive

Arguments

primitive: Primitive

Description

Tries to parse Primitive and returns Primitive double if primitive is String. Returns itself otherwise.

types

types(data: Data) returns Array

Arguments

data: Data

Description

Returns the type(s) of the given data. This will be an Array of strings. For example, a Container may return ["Container", "DefaultContainer"] and an empty Array may return ["Array", "null", "DefaultArray"].

Possible basic types are: Array, Container, Primitive, Dataset, and null. Implementations, like DefaultArray can vary depending on the execution environment.

unique

unique(array: Array) returns Array - a Data object with duplicates removed

Arguments

array: Array - an array of elements

Description

Remove duplicate data from the input Data. Elements are compared with the equals method. There is no guarantee as to which specific duplicates will be removed. The order of the elements in the returned value will be preserved.

uniqueBy

uniqueBy(array: Array, keySelector: Closure) returns Array - a Array with duplicate elements removed.

Arguments

array: Array - Array to deduplicate.

keySelector: Closure - Closure for extracting key from array entries to deduplicate over.

Description

Remove duplicates from the input Array. Elements are compared using the provided 'keySelector' Closure function. Existing values take precedence over later values, such that repeated elements are resolved by removing the later-occurring element in the Array. The order of the elements in the returned value will be preserved.

unset

unset(container: Container, field: String) returns Container

Arguments

container: Container

field: String

Description

Returns a container who is the same as the provided container but with the field removed. Depending on the container implementation used in RuntimeContext#getDataTypeImplementation() the returned container may or may not be the same object as the input.

uuid

uuid() returns Primitive

Arguments

Description

Returns a random uuid String.

values

values(container: Container) returns Array

Arguments

container: Container

Description

Returns an array of the values in the given container. The order of values corresponds to the fields being sorted alphabetically.

where

where(nullData: NullData, predicate: Closure) returns NullData

Arguments

nullData: NullData

predicate: Closure

Description

Catch-all for where applied to null, to disambiguate null from Array and Container.

where

where(array: Array, predicate: Closure) returns Array

Arguments

array: Array

predicate: Closure

Description

Filters the given Array, returning a new one containing only items that match the given predicate. Each array element is represented in the predicate by $. Example:

var array: [-1, 2, -3, -4, 5, -6]
 var positiveArray: array[where $ > 0] // positiveArray: [2, 5]

where

where(container: Container, predicate: Closure) returns Container

Arguments

container: Container

predicate: Closure

Description

Filters the given Container, returning a new one containing only items that match the given predicate. For each field-value pair in the Container, they are available in the predicate as $.field and $.value. If the predicate returns false, the resulting container won't have this field-value pair present. Example:

var container: {
   f1: 1; f2: 2; f3: 3; f4: 4;
 }
 var newContainer: container[where $.value < 2 || $.field == "f4"]
 // newContainer : {f1: 1; f4: 4;}

withError

withError(body: Closure, errorHandler: Closure) returns Data - the result value of either the body, or the error handler if it was called.

Arguments

body: Closure - The code to handle errors from.

errorHandler: Closure - The code to handle errors with.

Description

withError executes the code given in body. If any errors or exceptions occur, the code in errorHandler is called, with $error representing information about the error (structure below).

$error looks like:

{
    "cause": "Some string explaining what went wrong",
    "stack": [{ // Stack trace of where the error occurred. The top most stack frame is where
                // it occurred.
        "package": "Whistle or Java package name",
        "file": "file://the/original/file/path.wstl",
        "function": "myFunctionName",
        "line": 99 // Line in the file where the error occurs
       },
       {
        "package": "Whistle or Java package name",
        "file": "file://the/original/file/path.wstl",
        "function": "myOtherFunctionName",
        "line": 33 // The line where myFunctionName in the stack frame is called.
       }, ...],
    "vars": {
      "x": ..., // value of x
      "y": ... // value of y
    }
  }

withSides

withSides(body: Closure) returns Data - merged side and main outputs from the given expression.

Arguments

body: Closure - the expression from which to capture and merge side outputs.

Description

Executes the given expression, merging its output with any side outputs that are written within (including by other functions or expressions called by this one).

Targets

set

set(var: optional String, field: String, mergeMode: optional String): ...

Arguments

var: optional String - The variable to write to. Defaults to $this.

field: String - The path on the var to write. An empty string will write directly to the var.

mergeMode: optional String - The mode to use for merging. Possible options are:

  • replace - replace the given var's given field with the data.
  • merge - recursively merge the given var's given field with the data.
  • append - append the data as the last element in given var's given (array) field.
  • extend - extend the given var's given field with the data. For arrays this concatenates, for containers this adds only missing fields.

Description

Writes to the specified path on either the specified variable or to the output of the enclosing block (if var is omitted).

For example:

result: setSomeVars(100)

def setSomeVars(num) {
  var my_var: 0 // Although the following statements will be able to set the vars without them
                // being declared here, we need these declarations to read them later,
                // or the transpiler will complain.
  var my_var2: 0

  set("my_var", ""): num // Sets directly to my_var, overwriting the 0 with num (100)
  set("hundred"): my_var // Reads the prior value of 100, and sets it on field "hundred"
                         // on the output of this block. Same as doing:
                         // hundred: my_var

  set("my_var2", "field"): num + 1 // my_var2 becomes a container, and sets field "field"
                                   // on it to 101
  set("my_var2", "field2.value"): num + 10 // Add a new field to my_var2 (alongside the
                                           // prior) and set the nested value to 110.
  set("$this", "nested"): my_var2 // Sets field "nested" on the output of this block.
}

// result is now {
//    hundred: 100
//    nested: {
//      field: 101
//      field2: {
//        value: 110
//      }
//    }
//}

side

side(path: String, mergeMode: optional String): ...

Arguments

path: String - Path on the side output to write to. These are then merged with the main output of withSides.

mergeMode: optional String - The mode to use for merging. Possible options are:

  • replace - replace the given field with the data.
  • merge - recursively merge the given field with the data (default).
  • append - append the data as the last element in the given (array) field.
  • extend - extend the given field with the data. For arrays this concatenates, for containers this adds only missing fields.

Description

Writes to a side output.

For example:

// or equivalently side my_field:...
side("my_field"):... // will write to the my_field field of the side output which is then
                       // merged in withSides.

// A complete usecase:

result: withSides({
  one: 1
  addSomeSides(333)
  two: 2
})

// ... somewhere later on

def addSomeSides(num) {
  side sideNum.value: num
  // or equivalently side("sideNum.value"): num
}

// result will be {
//  one: 1
//  two: 2
//  sideNum: {
//    value: 333
//  }
// }
// Do note that the field ordering here is for illustration, no ordering is guaranteed
// by the side target.