Built-in constants are constants provided by the language that can be used without being defined in code.
Built-in constants are defined using only uppercase letters and _.
Built-in functions are also provided through the same mechanism as built-in constants.
- Built-in Object Class Constants
- Constants
- Mathematical Functions
- Stream Functions
REVERSEReverse Stream OrderSHUFFLERandomize Stream OrderDISTINCT/UNIQRemove Duplicate Elements from StreamJOINConcatenate Stream into StringSPLITSplit String into StreamLINESSplit String by LinesKEYSGet Stream of Object KeysVALUESGet Stream of Object ValuesINVERTReturns Object Mapping Values to KeysSUMSum of Stream ElementsMINMinimum Value of StreamMAXMaximum Value of StreamCOUNTNumber of Stream ElementsAND/ALLCheck if All are TrueOR/ANYCheck if Any is TrueFIRSTGet First Element of StreamLASTGet Last Element of StreamSINGLEGet Only Element of StreamSORTSort Stream in Ascending OrderSORTRSort Stream in Descending OrderINDEXEDConvert to Stream with IndicesGROUPGroup Stream by KeyCHUNKSplit Stream into Fixed-Size ArraysTAKEGet Beginning of StreamTAKERGet End of StreamDROPDiscard Beginning of StreamDROPRDiscard End of StreamFILTER/GREPFilter Stream by ConditionREDUCEAccumulate Stream ElementsTO_STRINGStringificationTO_NUMBERNumericalizationTO_BOOLEANBooleanizationTO_ARRAYConvert Stream to ArrayTO_OBJECTConvert Stream of Entries to Object::LET/LETPass Value to Block and Return Block’s Result::ALSO/ALSOPass Value to Block and Return Original ValueLAZYLazy Evaluation and Caching Function
Built-in Object Class Constants#
You can reference classes of various built-in objects.
VALUENULL_CLASSINTDOUBLEBOOLEANSTRINGREGEXARRAYOBJECTFUNCTIONSTREAMPROMISEBLOB
Constants#
Various constants representing special values.
| Constant | Meaning |
|---|---|
NULL N |
NULL value |
TRUE T |
True |
FALSE F |
False |
EMPTY E |
Empty stream |
LOOP |
Stream that infinitely generates NULL |
Mathematical built-in constants.
| Constant | Meaning |
|---|---|
MATH.PI |
Pi |
MATH.E |
Napier’s number |
String-related built-in constants.
| Constant | Meaning |
|---|---|
LT |
< |
GT |
> |
AMP |
& |
APOS |
' |
QUOT |
" |
BOM |
"\uFEFF" (Byte Order Mark) |
Mathematical Functions#
ABS Get Absolute Value#
ABS(value: NUMBER): NUMBER
Returns the absolute value of the first argument.
$ xa 'ABS(-10)'
# 10
FLOOR Round Down to Integer#
FLOOR(number: NUMBER): INT
Rounds the first argument down to the nearest smaller integer.
$ xa 'FLOOR(1.5)'
# 1
DIV Integer Part of Division#
DIV(x: NUMBER; y: NUMBER): NUMBER
Divides x by y and returns the integer part of the result.
$ xa 'DIV(10; 3)'
# 3
SQRT Get Square Root#
SQRT(number: NUMBER): NUMBER
Returns the positive square root of the first argument.
SQRT(number: NUMBER): NUMBER
Returns the positive square root of the first argument.
$ xa '"$%.3f( SQRT(100.0) )"'
# 10.000
SIN Sine#
SIN(number: NUMBER): NUMBER
Interprets the first argument as radians and returns its sine.
$ xa '"$%.3f( SIN(PI / 2) )"'
# 1.000
COS Cosine#
COS(number: NUMBER): NUMBER
Interprets the first argument as radians and returns its cosine.
$ xa '"$%.3f( COS(0) )"'
# 1.000
TAN Tangent#
TAN(number: NUMBER): NUMBER
Interprets the first argument as radians and returns its tangent.
$ xa '"$%.3f( TAN(PI / 4) )"'
# 1.000
POW Power#
POW(base: NUMBER; exponent: NUMBER): NUMBER
Returns the result of raising the first argument to the power of the second argument.
$ xa 'POW(2; 3)'
# 8.0
EXP Exponential Function#
EXP(number: NUMBER): NUMBER
Returns the exponential function (base e) of the first argument.
$ xa '"$%.3f( EXP(1) )"'
# 2.718
$ xa '"$%.3f( EXP(2) )"'
# 7.389
LOG Natural Logarithm#
LOG(number: NUMBER): NUMBER
Returns the natural logarithm (base e) of the first argument.
$ xa '"$%.3f( LOG(MATH.E) )"'
# 1.000
RAND Get Random Number#
RAND(): DOUBLE
RAND([from: NUMBER; ]until: NUMBER): INT
When called without arguments, returns a decimal between 0 (inclusive) and 1 (exclusive).
When called with 1 argument, returns an integer between 0 (inclusive) and until (exclusive).
When called with 2 arguments, returns an integer between from (inclusive) and until (exclusive).
Stream Functions#
REVERSE Reverse Stream Order#
REVERSE(stream: STREAM<VALUE>): STREAM<VALUE>
Returns a stream with the elements of the first argument stream in reverse order.
$ xa 'REVERSE(1 .. 3)'
# 3
# 2
# 1
SHUFFLE Randomize Stream Order#
<T> SHUFFLE(stream: T,): T,
Returns a stream with the elements of stream randomly rearranged.
DISTINCT / UNIQ Remove Duplicate Elements from Stream#
Returns a stream with duplicate elements removed.
UNIQ is an alias of DISTINCT and has the same behavior.
DISTINCT can be called in 2 ways.
Duplicate Determination by Elements Themselves#
DISTINCT(stream: STREAM<VALUE>): STREAM<VALUE>
When called with 1 argument, it uses the stream’s elements themselves to determine duplicates and returns a stream with duplicates removed.
$ xa '1, 2, 3, 3, 3, 2, 1, 0 >> DISTINCT'
# 1
# 2
# 3
# 0
Duplicate Determination by Key Getter Function#
DISTINCT(by: keyGetter: VALUE -> VALUE; stream: STREAM<VALUE>): STREAM<VALUE>
When the first argument is a by parameter, it applies the keyGetter function to each element of the second argument and determines duplicates based on the result.
The following example determines duplicates by the remainder when each element is divided by 10.
$ xa '13, 21, 24, 33, 31, 34 >> DISTINCT[by: x -> x % 10]'
# 13
# 21
# 24
JOIN Concatenate Stream into String#
JOIN([separator: STRING; ]stream: STREAM<STRING>): STRING
Returns a string with each element of the second argument stream concatenated with the first argument separator. If the first argument is omitted, , is used.
$ xa 'JOIN("|"; "a", "b", "c")'
# a|b|c
$ xa 'JOIN("a", "b", "c")'
# a,b,c
The separator and each element of the stream are stringified.
$ xa 'JOIN(0; 1, "b", {`&_`: _ -> "c"}{})'
# 10b0c
When used with partial application, it becomes easier to incorporate into pipe chains.
$ xa '1 .. 3 | _ * 10 >> JOIN["|"]'
# 10|20|30
SPLIT Split String into Stream#
SPLIT([separator: [by: ]STRING; ][limit: [limit: ]INT; ]string: STRING): STREAM<STRING>
Splits string by separator and returns each part as a stream. If separator is omitted, , is used.
Note that it returns a stream rather than an array for compatibility with the pipe operator.
SPLIT conceptually performs the inverse operation of JOIN.
separator and string are stringified and evaluated.
$ xa 'SPLIT("|"; "a|b|c")'
# a
# b
# c
$ xa 'SPLIT("a,b,c")'
# a
# b
# c
When limit is specified, the string is split into at most limit elements, and the limit-th element contains the entire remaining string.
$ xa 'SPLIT("|"; limit: 2; "a|b|c|d")'
# a
# b|c|d
By using with partial application, it becomes easier to incorporate into pipe chains.
$ xa '"10|20|30" >> SPLIT["|"] | +_ / 10'
# 1.0
# 2.0
# 3.0
LINES Split String by Lines#
LINES(string: STRING): STREAM<STRING>
Splits string by line breaks and returns each line as a stream.
Line break characters are removed from the resulting lines.
If string ends with a line break, only one trailing line break is ignored.
$ xa 'LINES("A\nB\nC") >> TO_ARRAY >> JSONS'
# ["A","B","C"]
$ xa 'LINES("A\nB\nC\n") >> TO_ARRAY >> JSONS'
# ["A","B","C"]
$ xa 'LINES("A\nB\nC\n\n") >> TO_ARRAY >> JSONS'
# ["A","B","C",""]
An empty string returns an empty stream, and a string with only one line break returns a stream with one empty string.
$ xa 'LINES("") >> TO_ARRAY >> JSONS'
# []
$ xa 'LINES("\n") >> TO_ARRAY >> JSONS'
# [""]
All line break characters (LF, CR, CRLF) are recognized.
$ xa 'LINES("A\rB\nC\r\nD")'
# A
# B
# C
# D
KEYS Get Stream of Object Keys#
KEYS(object: OBJECT | STREAM<OBJECT>): STREAM<STRING>
Returns a stream of keys from object.
$ xa 'KEYS({a: 1; b: 2; c: 3})'
# a
# b
# c
When object is a stream, returns a flattened stream that yields keys from each object element in sequence.
$ xa 'KEYS({a: 1; b: 2}, {c: 3; d: 4})'
# a
# b
# c
# d
VALUES Get Stream of Object Values#
VALUES(object: OBJECT): STREAM<VALUE>
Returns a stream of values of the first argument object.
$ xa 'VALUES({a: 1; b: 2; c: 3})'
# 1
# 2
# 3
INVERT Returns Object Mapping Values to Keys#
INVERT(object: OBJECT<VALUE>): OBJECT<STRING>
Returns a new object where the values of object map to their corresponding keys.
$ xa 'INVERT({a: "apple"; b: "banana"; c: "cherry"})'
# {apple:a;banana:b;cherry:c}
Values are stringified when treated as keys.
$ xa '
Fruit := {
new: value -> Fruit{value: value}
`&_`: this -> "Fruit[$(this.value)]"
}
INVERT({
a: Fruit.new("apple")
b: Fruit.new("banana")
c: Fruit.new("cherry")
})
'
# {Fruit[apple]:a;Fruit[banana]:b;Fruit[cherry]:c}
If values are duplicated, one of the keys for that value will be mapped.
$ xa '
object := {a: "apple"; b: "banana"; c: "apple"}
inverted := INVERT(object)
inverted.apple >> object
'
# apple
Which key is mapped is undefined.
SUM Sum of Stream Elements#
SUM(numbers: STREAM<NUMBER>): NUMBER
Returns the value obtained by adding each element of the first argument stream.
$ xa 'SUM(1 .. 3)'
# 6
MIN Minimum Value of Stream#
MIN(numbers: STREAM<NUMBER>): NUMBER
Returns the minimum value of the first argument stream.
If the stream is empty, returns NULL.
$ xa 'MIN(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5)'
# 1
$ xa 'MIN(,)'
# NULL
MAX Maximum Value of Stream#
MAX(numbers: STREAM<NUMBER>): NUMBER
Returns the maximum value of the first argument stream.
If the stream is empty, returns NULL.
$ xa 'MAX(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5)'
# 9
$ xa 'MAX(,)'
# NULL
COUNT Number of Stream Elements#
COUNT(stream: STREAM<VALUE>): INT
Returns the number of elements in the first argument stream.
For non-streams, returns 1.
$ xa 'COUNT(1, 2, 3)'
# 3
$ xa 'COUNT(1)'
# 1
$ xa 'COUNT(,)'
# 0
AND / ALL Check if All are True#
<T> AND(boolean1: STREAM<T>[; boolean2: STREAM<T>]): T | BOOLEAN
Determines whether all passed elements evaluate to true.
If there are no elements, returns true.
ALL is an alias of AND and has the same behavior.
$ xa 'AND(TRUE; TRUE)'
# TRUE
$ xa 'AND(TRUE; FALSE)'
# FALSE
$ xa 'AND(FALSE; FALSE)'
# FALSE
$ xa 'TRUE AND FALSE'
# FALSE
$ xa 'AND(TRUE, FALSE; TRUE, FALSE)'
# FALSE
$ xa '1 .. 50 | _ != 39 >> AND'
# FALSE
More precisely, this function returns the first element whose booleanization is false, or TRUE if none is found.
As soon as the first element whose booleanization is false is found, further stream iteration and element booleanization are skipped.
Unlike the && operator, which skips evaluation of the right-hand side itself based on the left-hand side value, each argument itself is evaluated before the function executes.
$ xa '1, "a", TRUE, 0, "b" >> AND'
# 0
$ xa '1, "a", TRUE, 2, "b" >> AND'
# TRUE
$ xa '
list := []
5 .. -5 | (
list += _
_
) >> AND
list
'
# [5;4;3;2;1;0]
$ xa '
list := []
(
list += "left"
FALSE
) AND (
list += "right"
TRUE
)
list
'
# [left;right]
OR / ANY Check if Any is True#
<T> OR(boolean1: STREAM<T>[; boolean2: STREAM<T>]): T | BOOLEAN
Determines whether any of the passed elements evaluate to true.
If there are no elements, returns false.
ANY is an alias of OR and has the same behavior.
$ xa 'OR(TRUE; TRUE)'
# TRUE
$ xa 'OR(TRUE; FALSE)'
# TRUE
$ xa 'OR(FALSE; FALSE)'
# FALSE
$ xa 'TRUE OR FALSE'
# TRUE
$ xa 'OR(TRUE, FALSE; TRUE, FALSE)'
# TRUE
$ xa '1 .. 50 | _ != 39 >> OR'
# TRUE
Other properties follow those of the AND function.
FIRST Get First Element of Stream#
FIRST(stream: STREAM<VALUE>): VALUE
Returns the first element of the first argument stream. If the stream is empty, returns NULL.
If a non-stream is passed, returns that value as-is.
$ xa 'FIRST(4, 5, 6)'
# 4
$ xa 'FIRST(4)'
# 4
$ xa 'FIRST(,)'
# NULL
LAST Get Last Element of Stream#
LAST(stream: STREAM<VALUE>): VALUE
Returns the last element of the first argument stream. If the stream is empty, returns NULL.
If a non-stream is passed, returns that value as-is.
$ xa 'LAST(4, 5, 6)'
# 6
$ xa 'LAST(6)'
# 6
$ xa 'LAST(,)'
# NULL
SINGLE Get Only Element of Stream#
<T> SINGLE(stream: STREAM<T>): T
Returns the only element of the first argument stream. Throws an error if the stream is empty or has multiple elements.
If a non-stream is passed, returns that value as-is.
$ xa 'SINGLE(4, 5, 6) !? "Error"'
# Error
$ xa 'SINGLE(6)'
# 6
$ xa 'SINGLE(,) !? "Error"'
# Error
SORT Sort Stream in Ascending Order#
Sorts a stream in ascending order.
SORT has 3 ways of calling.
Sort by Natural Ordering#
SORT(stream: STREAM<VALUE>): STREAM<VALUE>
When called with 1 argument, returns a stream with the elements of that stream sorted in ascending order.
$ xa '3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5 >> SORT >> JOIN[" "]'
# 1 1 2 3 3 4 5 5 5 6 9
Sort by Comparison Function#
SORT(comparator: VALUE, VALUE -> INT; stream: STREAM<VALUE>): STREAM<VALUE>
When called with 2 arguments, sorts the second argument stream using the first argument comparison function.
The following example sorts by the remainder when dividing each element by 3.
$ xa '1 .. 9 >> SORT[a, b -> a % 3 <=> b % 3] >> JOIN[" "]'
# 3 6 9 1 4 7 2 5 8
Sort by Key Getter Function#
SORT(by: key_getter: VALUE -> VALUE; stream: STREAM<VALUE>): STREAM<VALUE>
If the first argument is a by parameter, applies the key_getter function to each element of the second argument, compares the results, and sorts.
The following example sorts by the remainder when dividing each element by 3.
$ xa '1 .. 9 >> SORT[by: x -> x % 3] >> JOIN[" "]'
# 3 6 9 1 4 7 2 5 8
SORTR Sort Stream in Descending Order#
SORTR(stream: STREAM<VALUE>): STREAM<VALUE>
SORTR(comparator: VALUE, VALUE -> INT; stream: STREAM<VALUE>): STREAM<VALUE>
SORTR(by: key_getter: VALUE -> VALUE; stream: STREAM<VALUE>): STREAM<VALUE>
Sorts a stream in descending order.
Except that the sort is in descending order, it is the same as the SORT function.
$ xa '3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5 >> SORTR >> JOIN[" "]'
# 9 6 5 5 5 4 3 3 2 1 1
INDEXED Convert to Stream with Indices#
<T> INDEXED(stream: STREAM<T>): STREAM<[INT; T]>
Returns a stream of 2-element arrays with each element of stream paired with its 0-based index.
$ xa '"a", "b", "c" >> INDEXED'
# [0;a]
# [1;b]
# [2;c]
GROUP Group Stream by Key#
<T, K> GROUP([keyGetter: [by: ]T -> K; ]stream: STREAM<T>): STREAM<[K; ARRAY<T>]>
Applies keyGetter to each element of stream, groups values with the same key into arrays as entries, and returns them as a stream.
If keyGetter is omitted, groups using the elements themselves as keys.
Entry arrays are in the order in which that key first appeared.
$ xa '"apple", "cherry","banana", "banana", "apple" >> GROUP'
# [apple;[apple;apple]]
# [cherry;[cherry]]
# [banana;[banana;banana]]
$ xa '
{category: "fruit" ; value: "apple" },
{category: "fruit" ; value: "banana"},
{category: "animal"; value: "cat" },
>> GROUP[by: x -> x.category]
'
# [fruit;[{category:fruit;value:apple};{category:fruit;value:banana}]]
# [animal;[{category:animal;value:cat}]]
If the keys can be stringified, they can be easily grouped into objects by the TO_OBJECT function.
$ xa '
object := (
{category: "fruit" ; value: "apple" },
{category: "fruit" ; value: "banana"},
{category: "animal"; value: "cat" },
>> GROUP[by: x -> x.category]
>> TO_OBJECT
)
object.fruit() | _.value
'
# apple
# banana
CHUNK Split Stream into Fixed-Size Arrays#
CHUNK(size: NUMBER; stream: STREAM<VALUE>): STREAM<ARRAY<VALUE>>
Returns a stream of arrays grouping elements of the second argument stream by the size specified in the first argument.
$ xa '1, 2, 3, 4, 5 >> CHUNK[2]'
# [1;2]
# [3;4]
# [5]
TAKE Get Beginning of Stream#
TAKE(count: INT; stream: STREAM<VALUE>): STREAM<VALUE>
Returns a stream with the first count elements extracted from the second argument stream.
$ xa '1, 2, 3 >> TAKE[2]'
# 1
# 2
TAKER Get End of Stream#
TAKER(count: INT; stream: STREAM<VALUE>): STREAM<VALUE>
Returns a stream with the last count elements extracted from the second argument stream.
$ xa '1, 2, 3 >> TAKER[2]'
# 2
# 3
DROP Discard Beginning of Stream#
DROP(count: INT; stream: STREAM<VALUE>): STREAM<VALUE>
Returns a stream with the first count elements removed from the second argument stream.
$ xa '1, 2, 3 >> DROP[2]'
# 3
DROPR Discard End of Stream#
DROPR(count: INT; stream: STREAM<VALUE>): STREAM<VALUE>
Returns a stream with the last count elements removed from the second argument stream.
$ xa '1, 2, 3 >> DROPR[2]'
# 1
FILTER / GREP Filter Stream by Condition#
FILTER(predicate: [by: ]VALUE -> BOOLEAN; stream: STREAM<VALUE>): STREAM<VALUE>
Applies predicate to each element of stream and returns a stream containing only elements where the result is true.
GREP is an alias of FILTER and has the same behavior.
$ xa '1 .. 5 >> FILTER [ x => x % 2 == 1 ]'
# 1
# 3
# 5
$ xa '1 .. 5 >> FILTER[by: x -> x % 2 == 1]'
# 1
# 3
# 5
REDUCE Accumulate Stream Elements#
REDUCE(function: VALUE, VALUE -> VALUE; stream: STREAM<VALUE>): VALUE
REDUCE is a function that accumulates adjacent elements of stream by function and aggregates them into a single value.
REDUCE is often used as a function that processes streams by partial application.
$ xa 'REDUCE(a, b -> a + b; 1 .. 4)'
# 10
$ xa '1 .. 4 >> REDUCE[a, b -> a + b]'
# 10
This example applies a + b to all adjacent values from 1 to 4.
In other words, it is the same as 1 + 2 + 3 + 4.
If the stream has only one element or is not a stream, returns that element as-is.
$ xa '1 >> REDUCE[a, b -> a + b]'
# 1
If the stream is empty, returns NULL.
$ xa ', >> REDUCE[a, b -> a + b]'
# NULL
TO_STRING Stringification#
TO_STRING(value: VALUE): STRING
Converts a value to a string.
Has the same behavior as the &value operator.
$ xa 'TO_STRING(123)'
# 123
$ xa '1, 2, 3 >> TO_STRING'
# 123
TO_NUMBER Numericalization#
TO_NUMBER(value: VALUE): NUMBER
Converts a value to a number.
Has the same behavior as the +value operator.
$ xa 'TO_NUMBER("123")'
# 123
$ xa '1, 2, 3 >> TO_NUMBER'
# 6
$ xa 'TO_NUMBER(NULL)'
# 0
TO_BOOLEAN Booleanization#
TO_BOOLEAN(value: VALUE): BOOLEAN
Converts a value to a boolean.
Has the same behavior as the ?value operator.
$ xa 'TO_BOOLEAN("")'
# FALSE
$ xa 'TO_BOOLEAN("a")'
# TRUE
$ xa 'FALSE, TRUE, FALSE >> TO_BOOLEAN'
# TRUE
TO_ARRAY Convert Stream to Array#
ARRAY(stream: STREAM<VALUE>): ARRAY<VALUE>
Converts each element of the first argument stream to an array.
$ xa 'TO_ARRAY(1 .. 3)'
# [1;2;3]
TO_OBJECT Convert Stream of Entries to Object#
OBJECT(stream: STREAM<ARRAY<STRING; VALUE>>): OBJECT
Converts each element of the first argument stream into an object as entries.
$ xa 'TO_OBJECT(("a": 1), ("b": 2), ("c": 3))'
# {a:1;b:2;c:3}
::LET / LET Pass Value to Block and Return Block’s Result#
<I, O> I::LET(block: I -> O): O
<I, O> LET(receiver: I; block: I -> O): O
An extension function that passes the receiver’s value to block, executes it, and returns the block’s return value.
Useful for transforming values in the middle of method chains.
$ xa '"apple"::LET ( s => s & "banana" )::UC()'
# APPLEBANANA
::LET can also be used in a chain.
$ xa '"apple"::LET ( s => s & "banana" )::LET ( s => s::UC() )'
# APPLEBANANA
Usage with Streams#
Due to the nature of streams applying all methods to each element, the ::LET extension method cannot be used with streams.
$ xa '
Object := {
new: value -> Object{value: value}
LET: this, block -> "LET!"
}
stream := Object.new(1), Object.new(2), Object.new(3)
stream::LET ( s => s.value >> SUM )
'
# LET!
# LET!
# LET!
Instead, use the LET function which can also handle streams.
While 2 characters longer, it works roughly the same way as stream::(LET) ( s => ... ).
$ xa '
Object := {
new: value -> Object{value: value}
LET: this, block -> "LET!"
}
stream := Object.new(1), Object.new(2), Object.new(3)
stream::(LET) ( s => s.value >> SUM )
'
# 6
::ALSO / ALSO Pass Value to Block and Return Original Value#
<T> T::ALSO(block: T -> VALUE): T
<T> ALSO(receiver: T; block: T -> VALUE): T
An extension function that passes the receiver’s value to block, executes it, and returns the receiver’s value.
Per invocation, the side effects of block occur exactly once.
Useful for using or modifying values in the middle of method chains.
$ xa '
variable := ""
"apple"::ALSO ( s =>
variable = variable & s
)
variable
'
# apple
Other characteristics are generally the same as LET.
LAZY Lazy Evaluation and Caching Function#
<T> LAZY(initializer: () -> T): () -> T
Returns a function that performs lazy evaluation and caching.
The initializer is called only once on the first call of the function returned by LAZY, and its result is cached.
If the initializer returns a stream, that stream is resolved.
$ xa -q '
counter := 1
lazy := LAZY ( =>
counter++
counter
)
OUT << lazy()
OUT << lazy()
OUT << lazy()
'
# 2
# 2
# 2
This function is convenient when combined with delegated variables, as it allows you to omit the function call operator.
$ xa -q '
time := 0
\now := LAZY ( => time )
time = 100
OUT << now
time = 200
OUT << now
'
# 100
# 100