The Standard Library (stdlib)
Broad collection of Rel relations that perform essential and commonly used tasks.
^Date
View source^Date(n, d)Create a Date, d, representing the date at day n of the proleptic Gregorian calendar.
Example:
def output(d) = ^Date(734503, d)
//output> 2012-01-01For more details, see the rel:base:^Date docstring.
^Date
View source^Date[year in Int, month in Int, day in Int]Create a Date from its three components: year, month and day. The three arguments are required to be Int64.
^Date
View source^Date[dt in DateTime, tz in String]Create a Date from a DateTime, with timezone tz.
The timezone argument is necessary for the Date because DateTime is an instant of time
that is timezone independent. For different locations on earth (timezones), a DateTime has
different dates.
^DateTime
View source^DateTime(n, dt)Create a DateTime, dt, representing the date at millisecond n of the proleptic Gregorian calendar.
Example:
def output(dt) = ^DateTime(63568386000000, dt)
//output> 2015-05-27T05:00:00.000ZFor more details, see the rel:base:^DateTime docstring.
^DateTime
View source^DateTime[year, month, day, hour, minute, second, millisecond, tz in String]Create a DateTime from a year, month, day, hour, minute, second, and millisecond.
The timezone argument tz is necessary to correctly interpret what instant in time this is.
There can be multiple DateTime values for one set of arguments: for example, with the
ending of daylight saving time at 2am, every time between 1am and 2am occurs twice and has
two corresponding instants of time.
For part values that are out of range, there are no tuples (there is no error).
^DateTime
View source^DateTime[date, hour, minute, second, millisecond, tz in String]Create a DateTime from a date, hour, minute, second, and millisecond.
This constructor uses the year, month, and day from the date and then
constructs a DateTime in the same way as the constructor with all parts as arguments.
^DateTime
View source^DateTime[year, month, day, tz in String]Create a DateTime for the given year, month, and day, with the time components all set to 0.
The resulting DateTime is the first millisecond for the given date and time zone tz.
See the ^DateTime constructor with time components as arguments for more details.
^DateTime
View source^DateTime[date in Date, tz in String]Create a DateTime for the given Date, with the time components all set to 0.
The resulting DateTime is the first millisecond of the given Date and time zone tz.
See the ^DateTime constructor with time components as arguments for more details.
^FilePos
View source^FilePos(y, x)Brings the value type constructor ^FilePos from the module rel:base into the global namespace.
For more details, see the rel:base:^FilePos docstring.
∨
View sourceF or G
F ∨ GLogical or (disjunction), for boolean (arity 0, true or false) arguments F and G.
acos
View sourceacos[x]
acos(x, ac)Arccosine of x. ac is the arccosine of x given in radians.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Cosine of ac. Must be grounded. |
ac | FloatBinary[#64] | Arccosine of x in radians. |
Explanation
Defined for x between -1 and 1 (inclusive).
The value of ac ranges from 0 to π.
Arccosine is sometimes called “inverse cosine.”
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the arccosine of 0:
def output = acos[0]
//output> 1.5707963267948966Calculate the arccosine of -1 using full expression:
def output(x) = acos(-1, x)
//output> 3.141592653589793Confirm that 1.5707963267948966 is the arccosine of 0:
def output = acos(0, 1.5707963267948966)
//output> () // trueSee Also
acosh
View sourceacosh[x]
acosh(x, ach)Hyperbolic arccosine. ach is the hyperbolic arccosine of x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Hyperbolic cosine of ach. Must be grounded. |
ach | FloatBinary[#64] | Hyperbolic arccosine of x. |
Explanation
Defined for x >= 1.
Hyperbolic arccosine is sometimes called “inverse hyperbolic cosine.”
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the hyperbolic arccosine of 90:
def output = acosh[90]
//output> 5.192925985263684Calculate the hyperbolic arccosine of 180 using full expression:
def output(x) = acosh(180, x)
//output> 5.886096315311465Confirm that 5.192925985263684 is the hyperbolic arccosine of 90:
def output = acosh(90, 5.192925985263684)
//output> () // trueSee Also
acot
View sourceacot[x]
acot(x, act)Arccotangent. act is the arccotangent of x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Cotangent of act. Must be grounded. |
act | FloatBinary[#64] | Arccotangent of x. |
Explanation
Arccotangent is sometimes called “inverse cotangent.”
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the arccotangent of 1:
def output = acot[1]
//output> 0.7853981633974483Calculate the arccotangent of -1 using full expression:
def output(x) = acot(-1, x)
//output = -0.7853981633974483Confirm that 0.7853981633974483 is the arccotangent of 1:
def output = acot(1, 0.7853981633974483)
//output> () // trueSee Also
add
View sourceadd[x, y]
add(x, y, s)
x + yAddition of two numbers.
Addition of a DateTime/Date, x, with a time duration y.
Parameters
Numeric Data
| Parameter | Type | Description |
|---|---|---|
x | Number | First summand. |
y | Number | Second summand. |
s | Number | Sum x + y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | s |
|---|---|---|
Number | Same as x | Same as x |
Rational, FixedDecimal | SignedInteger[#64] | Same as x |
SignedInteger[#64] | SignedInteger[#128], Rational, FixedDecimal, FloatBinary[#64] | Same as y |
SignedInteger[#128] | SignedInteger[#64] | SignedInteger[#128] |
FloatBinary[#64] | SignedInteger[#64] | FloatBinary[#64] |
Two of the three arguments need to be grounded. Valid grounding combinations are as follows:
xandy.xands.yands.
Time Data
| Parameter | Type | Description |
|---|---|---|
x | Date, DateTime, date period, time period | First summand. |
y | Date, DateTime, date period, time period | Second summand. |
s | Date, DateTime, date period, time period | Sum x + y. |
The following combinations work:
x | y | s |
|---|---|---|
| date period, time period | Same date period, time period as x | Same date period, time period as x |
| date period, time period | DateTime | DateTime |
DateTime | date period, time period | DateTime |
| date period | Date | Date |
Date | date period | Date |
Two of the three arguments need to be grounded. Valid grounding combinations are as follows:
xandy.xands.yands.
Explanation
Addition evaluates the sum of x and y and assigns it to s.
In procedural languages, usually x and y are given.
In Rel — a declarative language — addition can be thought of as a mapping where x and y are the keys and s is the value, which is functionally dependent on x and y.
However, with addition — add(x, y, s) — it is sufficient to know any two of the three arguments.
The third one can always be inferred.
Usually x and y are given, but knowing x and s is enough to infer y.
Examples
Addition of Numbers
Add two integers using +:
def output = 1 + 2
//output> 3Add an integer and a float using add:
def output = add[1, 2.5]
//output> 3.5Add two floats using full expression:
def output(x) = add(1.7, 2.8, x)
//output> 4.5Add integer to a rational:
def output = 1 + rational[16][2, 3]
//output> 5/3Addition of Time
Add time to a timestamp:
def output:tomorrow = datetime_now + ^Day[1]
def output:next_hour = datetime_now + ^Hour[1]Add weeks to a date:
def output = 2022-12-24 + ^Week[2]
//output> 2023-01-07Add seconds together:
def output = ^Second[1] + ^Second[2]
//output> 3See Also
Any
View sourceAny(x)Holds for any x, where x exists. (Any functions as a wildcard.)
Example:
Integrity constraint that tests whether x is of any type:
def R = (1, 3) ; (1, "foo")
ic any_ic {subset(R, (Int, Any) )}approx_eq
View sourceapprox_eq(tolerance, x, y)Approximate equality.
Use to compare scalar numbers and check if x and y are within the absolute tolerance (tolerance) of each other.
Parameters
| Parameter | Type | Description |
|---|---|---|
tolerance | SignedInteger[#64] or FloatBinary[#64] | Tolerance of the approximation. A positive number. Must be grounded. |
x | Number | A valid number. Must be the same data type as y. Must be grounded. |
y | Number | A valid number. Must be the same data type as x. Must be grounded. |
Explanation
“approximately equal” is defined as number values being within the absolute tolerance (tolerance)
of each other, or non-number values being equal.
The parameter tolerance stands for the absolute tolerance and must be of type SignedInteger[#64] or FloatBinary[#64].
Also, tolerance must be a positive number; negative numbers will return false
x and y should be of the exact same data type.
For example, x and y can be of type FixedDecimal or Rational, but types must have the same bits and precision.
If x or y is not a number, approx_eq defaults to eq.
Examples
Approximate equality determined as true:
def output = approx_eq(0.05, 0.1, 0.15)
//output> () // trueApproximate equality determined as false:
def output = approx_eq(0.01, 0.1, 0.15)
//output> // falseSee Also
approx_equal
View sourceapprox_equal(tolerance, R, S)Approximate relational equality.
To hold true, the values in the last column of R must be approximately equal to values in the last column of S
given the same key (prefix).
Parameters
| Parameter | Type | Description |
|---|---|---|
tolerance | SignedInteger[#64] or FloatBinary[#64] | A positive integer or float. Must be grounded. |
R | Relation | A relation with corresponding keys and last elements that can be compared to S. Must be grounded. |
S | Relation | A relation with corresponding keys and last elements that can be compared to R. Must be grounded. |
Explanation
Two relations R and S are considered “relationally approximately equal” when for each tuple (k..., x) in S there exists a tuple (k..., y) in R where x and y are considered approximately equal.
This approximate equality is symmetric and holds equally true when the places of R and S are swapped.
See approx_eq for the details about approximate equality between two data values.
The parameter tolerance stands for the absolute tolerance and must be of type SignedInteger[#64] or FloatBinary[#64].
tolerance must be a positive number; negative numbers will evaluate to false.
Keys must match for approx_equal to be true.
All values of the last column in R and S must be of the exact same data type.
For example, the values can all be of type FixedDecimal or Rational, but types must have the same bits and precision.
Otherwise, approx_equal evaluates to false.
Note the correspondence between approx_equal and equal:
approx_equal(0, R, S) if and
only if equal(R, S).
approx_equal applies only to the values in the last column in R and S.
That is, if the values are not within tolerance, approx_equal will evaluate to false even if other arguments in the relations are within tolerance.
If full relation comparison functionality is required, see full_relation_approx_equal.
Examples
Approximate relational equality determined as true:
def salary1 = {("John", 10.0) ; ("Mary", 20.0); ("Paul", 17.0) ; ("Peter", 15.0) }
def salary2 = {("John", 9.99) ; ("Mary", 20.01); ("Paul", 17.0) ; ("Peter", 15.0) }
def output = approx_equal(0.1, salary1, salary2)
//output> () // trueApproximate relational equality determined as false:
def salary1 = {("John", 10.0) ; ("Mary", 20.0); ("Paul", 17.0) ; ("Peter", 15.0) }
def salary2 = {("John", 11.0) ; ("Mary", 21.0); ("Paul", 17.0) ; ("Peter", 15.0) }
def output = approx_equal(0.1, salary1, salary2)
//output> // falseApproximate relational equality determined as false because keys are different:
def salary1 = {("John", 10.0) ; ("Mary", 20.0); ("Paul", 17.0) ; ("Peter", 15.0) }
def salary3 = {("John", 9.99) ; ("Ben", 20.0); ("Paul", 17.0) ; ("Peter", 15.0) }
def output = approx_equal(0.1, salary1, salary3)
//output> // falseApproximate relational equality determined as false, even though the first arguments are within tolerance:
def coordinates1 = (1.0, 2.0); (3.0, 6.0)
def coordinates2 = (1.0000001, 2.0); (2.9999999, 6.0000001)
def output = approx_equal(0.001, coordinates1, coordinates2)
//output> // falseSee Also
full_relation_approx_equal, approx_eq, equal, and eq.
argmax
View sourceargmax[R]
argmax(R, am)For a relation R, find the tuples whose last elements are largest and return those tuples with the last element omitted.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | A relation whose tuples contain key-value pairs. Must be grounded. |
am | Number | A tuple in R with the largest last element, with last element omitted. |
Explanation
If tuples in R contain keys and values, argmax returns all the keys for the largest value.
Typically, argmax is used when the last elements of each tuple are numeric.
argmax is typically used with relations whose shortest tuple has length two.
Note that, for all unary relations, argmax results in a relation containing an empty tuple.
Examples
Find key for largest value of R:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(am) = argmax(R, am)
//output> "C"Find key for largest value of R where values are rationals:
def R = {("A", rational[64, 8, 3]); ("B", rational[64, 9, 7]); ("C", rational[64, 11, 4]); ("D", rational[64, 8, 3])}
def output = argmax[R]
//output> "C"Find the teams with the largest aggregated salary:
def salary = {("Burrow", 11,515,044); ("Chase", 18,211,606); ("Allen", 77,289,124); ("Diggs", 45,466,111)}
def member = {("Bengals", "Burrow"); ("Bengals", "Chase"); ("Bills", "Allen"); ("Bills", "Diggs")}
def team = {"Bengals"; "Bills"}
def output = argmax[d in team: sum[salary[p] for p in member[d]]]
//output> "Bengals"See Also
argmin
View sourceargmin[R]
argmin(R, am)For a relation R, find the tuples whose last elements are smallest and return those tuples with the last element omitted.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Source relation. Must be grounded. |
am | Any | A tuple in R with the smallest last element, with last element omitted. |
Explanation
If tuples in R contain keys and values, argmin returns all the keys for the smallest value.
Typically, argmin is used when the last elements of each tuple are numeric.
argmin is typically used with relations whose shortest tuple has length two.
Note that, for all unary relations, argmin results in a relation containing an empty tuple.
Examples
Find key for smallest value of R:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(am) = argmin(R, am)
//output> "A"
// "C"Find key for smallest value of R where values are rationals:
def R = {("A", rational[64, 8, 3]); ("B", rational[64, 9, 7]); ("C", rational[64, 11, 4]); ("D", rational[64, 7, 3])}
def output = argmin[R]
//output> "B"Find key for smallest value of R with tuples of various arity:
def R = {("A", 7.5); ("B", 8.6); ("C", "W", 9.7); ("D", "X", 7.5)}
def output = argmin[R]
//output> "A"
// "D", "X"Find the teams with the smallest aggregated salary:
def salary = {("Burrow", 11,515,044); ("Chase", 18,211,606); ("Allen", 77,289,124); ("Diggs", 45,466,111)}
def member = {("Bengals", "Burrow"); ("Bengals", "Chase"); ("Bills", "Allen"); ("Bills", "Diggs")}
def team = {"Bengals"; "Bills"}
def output = argmin[d in team: sum[salary[p] for p in member[d]]]
//output> "Bills"See Also
arity
View sourcearity[R]The arity of a relation. In some cases, it can be an over-approximation.
Arity is a higher-order relation that is always evaluated at compile-time.
Examples:
def output = arity[3]
//output> 1
def output = arity[{1; 2; 3}]
//output> 1
def output = arity[(1, 2)]
//output> 2
def output = arity[add]
//output> 3
def output = arity[{1; 2; (1,2)}]
//output> 1
// 2Arity can be used to do meta-programming in logic. For example, the following
abstraction verbalize implements specific cases using arity.
Examples:
@inline def verbalize[R] = "nullary", arity[R] = 0;
"unary", arity[R] = 1;
"binary", arity[R] = 2
def output = verbalize[true]
//output> "nullary"
def output = verbalize[1]
//output> "unary"Arity can be used in higher-order abstractions to check at compile-time that they are used correctly.
Arity can be used in integrity constraints to state expectation on EDB or IDB
relations. Because arity is evaluated at compile-time, it can catch mistakes in the
logic before the logic executes.
Example:
def p = (1, 2, 3)
ic { arity[p] = 3 }Note that there is a difference between R(_, _) and arity(R) = 2. The first requires
R to be non-empty, which is a run-time property of R.
asin
View sourceasin[x]
asin(x, as)Arcsine of x. ac is the arcsine of x given in radians.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Sine of as. Must be grounded. |
as | FloatBinary[#64] | Arcsine of x. |
Explanation
Defined for x between -1 and 1 (inclusive). The value of as ranges from -π/2 to π/2.
Only 64-bit float and 64-bit integer values for x are supported.
Arcsine is sometimes called “inverse sine.”
Examples
Calculate the arcsine of 1:
def output = asin[1]
//output> 1.5707963267948966Calculate the arcsine of -.5 using full expression:
def output(x) = asin(-.5, x)
//output> -0.5235987755982989Confirm that 1.5707963267948966 is the arcsine of 1:
def output = asin(1, 1.5707963267948966)
//output> () // trueSee Also
asinh
View sourceasinh[x]
asinh(x, ash)Hyperbolic arcsine. ash is the hyperbolic arcsine of x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Hyperbolic sine of ash. Must be grounded. |
ash | FloatBinary[#64] | Hyperbolic arcsine of x. |
Explanation
Hyperbolic arcsine is sometimes called “inverse hyperbolic sine.”
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the hyperbolic arcsine of 10:
def output = asinh[10]
//output> 2.99822295029797Calculate the hyperbolic arcsine of -1 using full expression:
def output(x) = asinh(-1, x)
//output> -0.881373587019543Confirm that 2.99822295029797 is the hyperbolic arcsine of 10:
def output = asinh(10, 2.99822295029797)
//output> () // trueSee Also
atan
View sourceatan[x]
atan(x, at)Arctangent. at is the arctangent of x in radians.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Tangent of at. Must be gounded. |
at | FloatBinary[#64] | Arctangent of x. |
Explanation
Arctangent is sometimes called “inverse tangent.”
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the arctangent of π/4:
def output = atan[pi_float64/4]
//output> 0.6657737500283538Convert degrees to radians and calculate arctangent using full expression:
def x = deg2rad[90]
def output(at) = atan(x, at)
//output> 1.0038848218538872Confirm that 0.6657737500283538 is the tangent of π/4:
def output = atan(pi_float64/4, 0.6657737500283538)
//output> () // trueSee Also
atan2
View sourceatan2[y, x]
atan2(y, x, at)Arctangent. at is the arctangent of the quotient y/x in radians.
Parameters
| Parameter | Type | Description |
|---|---|---|
y | FloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64] | coordinate of the 2D point . Must be gounded. |
x | UnsignedInteger[#64], SignedInteger[#64], FloatBinary[#64] | coordinate of the 2D point . Must be gounded. |
at | FloatBinary[#64] | Arctangent of x. |
Explanation
Arctangent is sometimes called “inverse tangent.”
The parameters x and y can be thought of as the and coordinates of the 2D point .
Examples
Calculate the arctangent of 50:
def output = atan2[100, 2.0]
//output> 1.550798992821746See Also
atanh
View sourceatanh[x]
atanh(x, ath)Hyperbolic arctangent. ath is the hyperbolic arctangent of x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Hyperbolic tangent of ath. Must be grounded. |
ath | FloatBinary[#64] | Hyperbolic arctangent of x. |
Explanation
Hyperbolic arctangent is sometimes called “inverse hyperbolic tangent.”
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the hyperbolic arctangent of -.7:
def output = atanh[-.7]
//output> -0.8673005276940532Calculate the hyperbolic arctangent of .7 using full expression:
def output(x) = atanh(.7, x)
//output> 0.8673005276940532Confirm that -0.8673005276940532 is the hyperbolic arctangent of -.7:
def output = atanh(-.7, -0.8673005276940532)
//output> () // trueSee Also
average
View sourceaverage[R]
average(R, m)The average (arithmetic mean) of a relation R.
average is an alias for mean.
For details, see the docstring for mean.
bigint
View sourcebigint[i]Create a BigInteger value from the given integer.
Examples:
string[factorial[bigint[50]]] = "30414093201713378043612608166064768844377641568960512000000000000"bigint_int64_convert
View sourceConvert a BigInteger to an Int64.Examples:
bigint_int64_convert[bigint[50]] = 50bitwise_and
View sourcebitwise_and[x, y]
bitwise_and(x, y, z)Bitwise and of two integers.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | SignedInteger, UnsignedInteger | Left operand. Must be grounded. |
y | SignedInteger, UnsignedInteger | Right operand. Must be grounded. |
z | SignedInteger, UnsignedInteger | The bitwise and of x and y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
|---|---|---|
SignedInteger, UnsignedInteger | Same as x. | Same as x. |
SignedInteger, UnsignedInteger | SignedInteger[#64], UnsignedInteger[#32] | Same as x. |
Examples
Bitwise and of 3 and 2:
def output = bitwise_and[3, 2]
//output> 2Bitwise and of two unsigned integers using full expression:
def output(z) = bitwise_and(0x11100, 0x00101, z)
//output> 256Bitwise and of unsigned and signed integers:
def output = bitwise_and[0x010b, -265]
//output> 3 // is an UnsignedInteger[#16]See Also
bitwise_or, bitwise_xor, bitwise_left_shift, bitwise_right_shift, bitwise_unsigned_right_shift, and bitwise_not.
bitwise_left_shift
View sourcebitwise_left_shift[x, y]
bitwise_left_shift(x, y, z)Bitwise left shift of an integer x by y bits.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | SignedInteger, UnsignedInteger | Operand. Must be grounded. |
y | SignedInteger, UnsignedIntegere | Bits for left shift. Must be grounded. |
z | SignedInteger, UnsignedInteger | The bitwise left shift of x and y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
|---|---|---|
SignedInteger, UnsignedInteger | Same as x. | Same as x. |
SignedInteger, UnsignedInteger | SignedInteger[#64], UnsignedInteger[#32] | Same as x. |
Explanation
The type of shift done depends on the type of x.
If x is signed, bitwise_left_shift performs a signed left shift (also known as an “arithmetic left shift”).
If x is unsigned, bitwise_left_shift performs an unsigned left shift (also known as a “logical left shift”).
Examples
Bitwise left shift of 8 by 1 bit:
def output = bitwise_left_shift[8, 1]
//output> 16Bitwise left shift of 1 by 10 bits using full expression:
def output(z) = bitwise_left_shift(1, 10, z)
//output> 1024Bitwise left shift of 0xf by 1 bit:
def output = bitwise_left_shift[0xF, 1]
//output> 30Bitwise left shift of unsigned integer:
def output = bitwise_left_shift[uint[64, 4028], 1]
//output> 8056See Also
bitwise_and, bitwise_or, bitwise_xor, bitwise_right_shift, bitwise_unsigned_right_shift, and bitwise_not.
bitwise_not
View sourcebitwise_not[x]
bitwise_not(x, z)Bitwise not of an integer.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | SignedInteger, UnsignedInteger | Operand. Must be grounded. |
z | SignedInteger, UnsignedInteger | The bitwise not of x. |
Not all numeric values can be mixed with each other. The following combinations work:
x | z | |
|---|---|---|
SignedInteger, UnsignedInteger | Same as x. | Same as x. |
Examples
Bitwise not of -9:
def output = bitwise_not[-9]
//output> 8Bitwise not of 8 using full expression:
def output(z) = bitwise_not(8, z)
//output> -9Bitwise not of 0x00011:
def output = bitwise_not[0x00011]
//output> 4294967278See Also
bitwise_and, bitwise_or, bitwise_xor, bitwise_left_shift, bitwise_right_shift, and bitwise_unsigned_right_shift.
bitwise_or
View sourcebitwise_or[x, y]
bitwise_or(x, y, z)Bitwise or of two integers.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | SignedInteger, UnsignedInteger | Left operand. Must be grounded. |
y | SignedInteger, UnsignedInteger | Right operand. Must be grounded. |
z | SignedInteger, UnsignedInteger | The bitwise or of x and y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
|---|---|---|
SignedInteger, UnsignedInteger | Same as x. | Same as x. |
SignedInteger, UnsignedInteger | SignedInteger[#64], UnsignedInteger[#32] | Same as x. |
Examples
def output = bitwise_or[3, 2]
//output> 3Bitwise or of 0x00011 and 0x11100 using full expression:
def output(z) = bitwise_or(0x00011, 0x11100, z)
//output> 69905Bitwise xor of two unsigned integers:
def output = bitwise_or[uint[64, 1024], uint[64, 2048]]
//output> 3072See Also
bitwise_and, bitwise_xor, bitwise_left_shift, bitwise_right_shift, bitwise_unsigned_right_shift, and bitwise_not.
bitwise_right_shift
View sourcebitwise_right_shift[x, y]
bitwise_right_shift(x, y, z)Bitwise right shift of an integer x by y bits that preserves the sign.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | SignedInteger, UnsignedInteger | Operand. Must be grounded. |
y | SignedInteger, UnsignedInteger | Bits for right shift. Must be grounded. |
z | SignedInteger, UnsignedInteger | The bitwise right shift of x and y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
|---|---|---|
SignedInteger, UnsignedInteger | Same as x. | Same as x. |
SignedInteger, UnsignedInteger | SignedInteger[#64], UnsignedInteger[#32] | Same as x. |
Examples
Bitwise right shift of 1024 by 1 bit:
def output = bitwise_right_shift[1024, 1]
//output> 512Bitwise right shift of -1024 by 1 bit using full expression:
def output(z) = bitwise_right_shift(-1024, 1, z)
//output> -512Bitwise right shift of unsigned integer by 2 bits:
def output = bitwise_right_shift[uint[64, 2048], 2]
//output> 512See Also
bitwise_and, bitwise_or, bitwise_xor, bitwise_left_shift, bitwise_unsigned_right_shift, and bitwise_not.
bitwise_unsigned_right_shift
View sourcebitwise_unsigned_right_shift[x, y]
bitwise_unsigned_right_shift(x, y, z)Bitwise unsigned right shift of an integer by y bits.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | SignedInteger, UnsignedInteger | Operand. Must be grounded. |
y | SignedInteger, UnsignedInteger | Bits for unsigned right shift. Must be grounded. |
z | SignedInteger, UnsignedInteger | The bitwise unsigned right shift of x and y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
|---|---|---|
SignedInteger, UnsignedInteger | Same as x. | Same as x. |
SignedInteger, UnsignedInteger | SignedInteger[#64], UnsignedInteger[#32] | Same as x. |
Examples
Bitwise unsigned right shift of 8 by 1 bit:
def output = bitwise_unsigned_right_shift[8, 1]
//output> 4Bitwise unsigned right shift of -8 by 2 bits:
def output(z) = bitwise_unsigned_right_shift(-8, 2, z)
//output> 4611686018427387902Bitwise unsigned right shift of unsigned integer by 3 bits:
def output = bitwise_unsigned_right_shift[uint[64, 8], 3]
//output> 1See Also
bitwise_and, bitwise_or, bitwise_xor, bitwise_left_shift, bitwise_right_shift, and bitwise_not.
bitwise_xor
View sourcebitwise_xor[x, y]
bitwise_xor(x, y, z)Bitwise xor (exclusive or) of two integers.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | SignedInteger, UnsignedInteger | Left operand. Must be grounded. |
y | SignedInteger, UnsignedInteger | Right operand. Must be grounded. |
z | SignedInteger, UnsignedInteger | The bitwise xor of x and y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
|---|---|---|
SignedInteger, UnsignedInteger | Same as x. | Same as x. |
SignedInteger, UnsignedInteger | SignedInteger[#64], UnsignedInteger[#32] | Same as x. |
Examples
Bitwise xor of 3 and 2:
def output = bitwise_xor[3, 2]
//output> 1 // is a SignedInteger[#64]Bitwise xor of 0x00011 and 0x11100 using full expression:
def output(z) = bitwise_xor(0x00011, 0x11100, z)
//output> 69905Bitwise xor of two unsigned integers:
def output = bitwise_xor[uint[64, 1024], uint[64, 2048]]
//output> 3072See Also
bitwise_and, bitwise_or, bitwise_left_shift, bitwise_right_shift, bitwise_unsigned_right_shift, and bitwise_not.
Boolean
View sourceBoolean(x)Holds if x is a Boolean.
Example:
def json = parse_json["""{"a": true, "b": false}"""]
def output(x) = json(:a, x) and Boolean(x)boolean_and
View sourceboolean_and(x, y, z)Logical AND operator for the Boolean data type.
Example:
def output(x, y, z) = boolean_and(x, y, z) and boolean_true(z)boolean_not
View sourceboolean_not(x,y)Negation(not) operator for the Boolean data type.
Example:
def output(x, y) = boolean_not(x, y) and boolean_false(x)boolean_or
View sourceboolean_or(x, y, z)Logical or operator for the Boolean data type.
Example:
def output(x, y, z) = boolean_or(x, y, z) and boolean_false(z)bottom
View sourcebottom[k, R]
bottom(k, R, index, x...)Select the bottom k tuples of relation R according to the sort order of R and add enumeration.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Source relation. Must be grounded. |
k | Int | Number of tuples to sort from the bottom of R. Must be grounded. |
index | Int | The new enumeration index starting at 1. |
x... | Tuple | A tuple in R associated with the new index index. |
Explanation
bottom is reverse_sort restricted to the last k tuples of R.
bottom puts the tuples of R in lexicographical order and then limits the result to the last k tuples.
The index indicates the tuples of R in reverse order.
For details on lexicographical ordering — particularly across data types — see enumerate.
Simlar to reverse_sort, bottom takes a relation R(x...) and produces a relation with the tuples (index, x...),
where the first element of each tuple (index) is an integer index that enumerates the bottom k tuples
in the original relation R.
Examples
Apply bottom to a relation with arity-1 tuples:
def output = bottom[2, {'a'; 'b'; 'c'; 'd'}]
//output> (1, 'd')
// (2, 'c')Apply bottom to a relation with arity-2 tuples:
def R = {('a', 1); ('b', 2); ('c', 3); ('d', 4); ('e', 5)}
def output = bottom[3, R]
//output> 1, e, 5
// 2, d, 4
// 3, c, 3See Also
top, enumerate, sort, and reverse_sort.
byte
View sourcebyte[str]
byte[str, i]
byte(str, i, b)Indexes into a string at byte position i, mapping each position i to a byte b, as a UInt8 value.
If a string contains Unicode characters, the byte at index i might be only a partial character.
Be careful with your indexing logic.
Both i and b can be optionally bound externally. When only str is bound, this is
the mapping from each index to its corresponding byte.
Examples: Indexing into a known byte index:
byte["abcd", 2] = 0x62
byte["中文例子", 2] = 0xb8Abstracting over the byte index:
equal(byte["中文"],
{ 1, 0xe4;
2, 0xb8;
3, 0xad;
4, 0xe6;
5, 0x96;
6, 0x87; })
equal((i : byte["awesome", i](0x65)), {3; 7})capture_group_by_index
View sourcecapture_group_by_index[regex, input_string, offset]A set of capture groups, each of the form (index, substring), where index is the capture group index, and substring
is the first regex match in input_string, starting at the character index specified by offset.
regex can be a string or a pattern.
Offsets (character indexes) start at 1.
Example:
capture_group_by_index["(\\d+):(\\d+)",
"Appointment from 12:45 to 1:30",
19]is equal to
{(1, "12"); (2, "45")}capture_group_by_name
View sourcecapture_group_by_name[regex, input_string, offset]A set of capture groups, each of the form (name, substring), where name is the capture group name, and substring
is the first regex match in input_string, starting at the character index specified by offset.
regex can be a string or a pattern.
Offsets (character indexes) start at 1.
Each capture group should have a unique name.
Example:
capture_group_by_name["(?<hour>\\d+):(?<minute>\\d+)",
"Appointment from 12:45 to 1:30",
19]is equal to
(("hour","12"); ("minute","45"))cart
View sourcecart[R, S]
R × SCartesian product.
Examples:
def output = 1 ✕ 2
//output> (1,2)
def output = {1; 2} ✕ {3; 4}
//output> (1,3)
// (1,4)
// (2,3)
// (2,4)ceil
View sourceceil[x]
ceil(x, c)Round up to the nearest integer.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Number | Number to be rounded up. Must be grounded. |
c | SignedInteger[#64] | Ceiling of x. |
Return type is the same as x.
Explanation
For positive x, ceil rounds away from 0.
For negative x, ceil rounds toward 0.
Examples
Calculate ceil for positive float:
def output = ceil[4.5]
//output> 5.0Calculate ceil for negative float using full expression:
def output(c) = ceil(-4.5, c)
//output> -4.0Calculate ceil for rational:
def output = ceil[rational[64, 8, 3]]
//output> 3/1See Also
floor, floor_to_int, trunc, trunc_to_int, and round.
char
View sourcechar[str]
char[str, i]
char(str, i, c)Indexes into a string at (Int) position i, mapping each index i to the i-th character, c.
Since this is indexed using character positions, the characters will always be whole Unicode characters.
A character is also known as a “Code Point” in the Unicode specification.
Both i and c can be optionally bound externally. When only str is bound, this is
the mapping from each character index to its corresponding character.
Examples:
Indexing into a known character index:
char["abcd", 2] = 'b'
char["中文例子", 2] = '文'Abstracting over the character index:
equal(char["中文"],
{ 1, "中"; 2, "文" })
equal((i : char["awesome", i]('e')), {3; 7})Char
View sourceChar(x)Holds if x is of type Char, which has a Unicode character as its value and is specified with single quotes.
Examples:
Integrity constraint that tests whether x is of type Char:
def R = 't'
ic mychar_ic(x in R)
Char(x)
}Schema defined in a relation using Char:
def myrelation(x in Char, y in Int) {
x = 'a' and y = 123
}
def output = myrelation
//output> (a, 123)clamp
View sourceclamp[low, high, value]
clamp(low, high, value, clamped)Limit value to a range between low and high.
The parameter clamped contains the “clamped” result.
Parameters
| Parameter | Type | Description |
|---|---|---|
low | Same as value. | Lower bound. Must be grounded. |
high | Same as value. | Upper bound. Must be grounded. |
value | Number | Value to be clamped. Must be grounded. |
clamped | Same as value | value limited to between low and high. |
Explanation
The resulting value clamped is equivalant to value as long as it is within the lower and upper bounds.
If value lies outside of these bounds, then clamped will take on the value of the bound that is closest to value.
In mathematical terms, this reads:
For example, if low and high are of type Float, value should also be of type Float.
Note that relations never contain duplicates.
If value is a relation with multiple values lower than low (or higher than high), clamp[low, high, value]
will contain only once the value low (high).
Examples
Clamp relation with integer values:
def low = 1
def high = 4
def value = {-4; 2; 7}
def output = clamp[low, high, value]
//output> 1
// 2
// 4Clamp relation with rationals. Note that relations never contain duplicates, thus only low and high values are included in output.
def low = rational[64, 7, 27]
def high = rational[64, 26, 27]
def value = {rational[64, 1, 27]; rational[64, 6, 27]; rational[64, 31, 27]}
def output = clamp[low, high, value]
//output> 7/27
// 26/27See Also
concat
View sourceconcat[val1, val2]String concatenation of two arbitrary values
Example:
concat["a", "b"] = "ab"
concat["a", 'b'] = "ab"
concat['a', "b"] = "ab"
concat['a', 'b'] = "ab"
concat["a_", 1] = "a_1"
concat[1, 3.14] = "13.14"contains
View sourcecontains(s, substring)True iff the second argument, substring, occurs as a substring in the first argument, s.
Examples:
contains("Rel is cool!", "Rel is cool!") // true
contains("Rel is cool!", " is coo") // true
contains("Rel is cool!", 'c') // true
contains("Rel is cool!", 'C') // falsecos
View sourcecos[x]
cos(x, c)Cosine of of x, where x is an angle given in radians.
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Angle in radians. Must be grounded. |
c | FloatBinary[#64] | Cosine of x. |
Explanation
Defined for non-infinite x.
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the cosine of π/6:
def output = cos[pi_float64/6]
//output> 0.8660254037844387Calculate the cosine of π/4 using full expression:
def output(x) = cos(pi_float64/4, x)
//output> 0.7071067811865476Confirm that 0.5000000000000001 is the cosine of π/3:
def output = cos(pi_float64/3, 0.5000000000000001)
//output> () // trueSee Also
cosh
View sourcecosh[x]
cosh(x, ch)Hyperbolic cosine. ch is the hyperbolic cosine of x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Hyperbolic angle. Must be grounded. |
ch | FloatBinary[#64] | Hyberbolic cosine of x. |
Explanation
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the hyperbolic cosine of 1:
def output = cosh[1]
//output> 1.5430806348152437Calculate the hyperbolic cosine of -7 using full expression:
def output(x) = cosh(-7, x)
//output> 548.317035155212Confirm that 1.5430806348152437 is the hyperbolic cosine of 1:
def output = cosh(1, 1.5430806348152437)
//output> () // trueSee Also
cot
View sourcecot[x]
cot(x, ct)Cotangent. ct is the cotangent of x, where x is in radians.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Angle in radians. Must be grounded. |
ct | FloatBinary[#64] | Cotangent of x. |
Explanation
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the cotangent of π/4:
def output = cot[pi_float64/4]
//output> 1.0000000000000002Convert degrees to radians and calculate cotangent using full expression:
def x = deg2rad[90]
def output(t) = cot(x, t)
//output> 6.123233995736766e-17Confirm that 1.0000000000000002 is the cotangent of π/4:
def output = cot(pi_float64/4, 1.0000000000000002)
//output> () // trueSee Also
count
View sourcecount[R]
count(R, n)Count the number n of tuples contained in the relation R.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | A general relation. Must be grounded. |
n | Integer | Number of tuples in R. |
Explanation
The relation count contains the higher-order tuple (R, n) if R is a relation with n tuples.
The form count[R] is generally used to count the number of tuples in a relation R.
The form count(R, n) is generally used to test whether R contains n tuples.
If R is empty, count[R] is false.
To get 0 instead, use left_override, as in count[R] <++ 0.
Examples
Count the number of tuples in a relation called employees:
def employees = {
("jane", 12);
("tran", 24);
("miguel", 36)
}
def output = count[employees]
//output> 3Count a singleton relation:
def output = count[5]
//output> 1Test if employees contains three tuples:
def output = count(employees, 3)
//output> () // trueSee Also
argmax, argmin, average, bottom, top, first, last, max, min, mode, and product.
csv_string
View sourcecsv_string[R]The string representation of relation that encodes as CSV using the configuration relation R.
Required keywords are:
:data: A set of relations mapping a file position, which can be a key of arbitrary length or type, to the corresponding value. This is the data that will be exported. We expect the data relation to be of form: data(:COLUMN_NAME, pos, val) Optional keywords::syntax: A relation containing syntax configuration. The following options can be specified::header: A relation with(Int, RelName)pairs, specifying the column names in the file, where theIntindices indicate the column order, and the column name is provided as a Symbol (of typeRelName). This option overrides the default (or existing) header names.:header_row: AnIntthat specifies the row where the file header is. The column names are specified by the content of that row, if they are not defined using the header option above. The values -1 and 0 indicate that no header is present and the system creates column names for you.:datarow: AnIntthat specifies the row from where to start parsing values into relations.:missingstrings: One or multipleStringvalues that should be interpreted as missing values. By default, only empty fields are considered missing.:delim: An ASCIICharthat delimits individual fields while parsing. Defaults to','.:quotechar: An ASCIICharthat signals a “quoted” field while parsing. Defaults to'"'.:escapechar: An ASCIICharused to “escape”quotechars and otherescapechars within a quoted (e.g., text) field. Defaults to'\\'.
Example using default CSV syntax
def csv_data(:ORDER, pos, v) = ((1,1); (2,2); (3,3))(pos, v)
def csv_data(:LINEITEM, pos, v) = ((1,100); (2,101); (3,102))(pos, v)
def csv_data(:QUANTITY, pos, v) = ((1,2); (2,15); (3,42))(pos, v)
def config[:data] = csv_data
def output = csv_string[config]Example using custom CSV syntax
def csv_data(:ORDER, pos, v) = ((1,1); (2,2); (3,3))(pos, v)
def csv_data(:LINEITEM, pos, v) = ((1,100); (2,101); (3,102))(pos, v)
def csv_data(:QUANTITY, pos, v) = ((1,2); (2,15); (3,42))(pos, v)
def config[:data] = csv_data
def config[:syntax, :delim] = '\t'
def config[:syntax, :quotechar] = '_'
def output = csv_string[config]Example with compound keys:
def csv_data(:ORDER, pos..., v) = (1, 2, 100; 2, 1, 40)(pos..., v)
def csv_data(:QUANTITY, pos..., v) = (1, 2, 10; 2, 1, 11; 3, 1, 12; 3, 2 ,13)(pos..., v)
def config[:data] = csv_data
def output = csv_string[config]Note that when using compound keys pos..., they are required to contain no specialized values.
This mean no RelNames like :id or any other specialized value like #(1) are allowed.
See Also
current_transaction_id
View sourcecurrent_transaction_idThe Transaction ID of the current transaction as an unsigned 128-bit integer.
This is comparable to Snowflake CURRENT_TRANSACTION, SQL Server CURRENT_TRANSACTION_ID,
and PostgreSQL txid_current.
date_add
View sourcedate_add[d, period]
d + periodAdd a Period to a Date
Example:
def d = parse_date["2021-09-21", "Y-m-d"]
def output = date_add[d, ^Day[20]]
//output> 2021-10-11date_day
View sourcedate_day[d]Day of the month for a Date, as an integer between 1 and 31, inclusive.
Example:
def d = parse_date["2014-10-31", "Y-m-d"]
date_day[d] = 31date_dayname
View sourcedate_dayname[d]Name of week-day (a String, e.g., Friday)
Example:
def t = parse_date["2014-01-31", "Y-m-d"]
def output = date_dayname[t]
//output> "Friday"date_dayofquarter
View sourcedate_dayofquarter[d]Day of quarter
Example:
def d = parse_date["2014-01-31", "Y-m-d"]
date_dayofquarter[d] = 31date_dayofweek
View sourcedate_dayofweek[d]Day of the week for a date, as an integer between 1 and 7, where 1 is Monday and 7 is Sunday. (That is, 5 for Friday.)
Example:
def d = parse_date["2014-01-31", "Y-m-d"]
date_dayofweek[d] = 5date_dayofweekofmonth
View sourcedate_dayofweekofmonth[d]Day of week of month, as an integer (e.g. 2 for second Friday of the month, 1 for the first Tuesday).
Example:
def t = parse_date["2014-01-31", "Y-m-d"]
date_dayofweekofmonth[t] = 5 // fifth Friday of that monthdate_dayofyear
View sourcedate_dayofyear[d]Day of year
Example:
def t = parse_date["2014-01-31", "Y-m-d"]
def output = date_dayofyear[t]
//output> 31date_daysinmonth
View sourcedate_daysinmonth[d]The number of days in the month for date d
Examples:
def d1 = parse_date["2014-01-30", "Y-m-d"]
date_daysinmonth[t] = 31
def d2 = parse_date["2014-02-11", "Y-m-d"]
date_daysinmonth[d2] = 28
def d = parse_date["2016-02-11", "Y-m-d"]
date_daysinmonth[d] = 29date_isleapyear
View sourcedate_isleapyear[d]True iff the year for date d is a leap year.
Examples:
def notleap = parse_date["2014-01-31", "Y-m-d"]
def leap = parse_date["2016-01-31", "Y-m-d"]
def output = date_isleapyear[notleap]
//output> // false
def output = date_isleapyear[leap]
//output> () // truedate_monthname
View sourcedate_monthname[d]The month name for date d, as a string.
Example:
def t = parse_date["2014-01-31", "Y-m-d"]
date_monthname[t] = "January"date_quarterofyear
View sourcedate_quarterofyear[d]Quarter to year
Example:
def d = parse_date["2014-01-31", "Y-m-d"]
date_quarterofyear[d] = 1date_subtract
View sourcedate_subtract[date, period]
date - periodSubtract a Period from a Date, giving another Date.
Example:
def d = parse_date["2021-09-21", "Y-m-d"]
def output = date_subtract[d, ^Day[1000]]
//output> 2018-12-26date_week
View sourcedate_week[d]Week of the year for a Date, as an integer, where the first week is the week that contains the first Thursday of the year. Ranges between 1 and 53, inclusive.
Example:
week[parse_date["2005-01-01", "Y-m-d"]] = 53 // 53rd week of 2004.
week[parse_date["2001-01-01", "Y-m-d"]] = 1date_year
View sourcedate_year[d]Year of a Date, as an integer.
Example:
date_year[parse_date["2020-05-22", "Y-m-d"]]
2020
^Year[date_year[parse_date["2020-05-22", "Y-m-d"]]]
(2020 years,)dates_period_days
View sourcedates_period_days[date1, date2]The difference in days between two dates date2 and date1 as a Day data type.
Example:
def days = dates_period_days[
2022-05-12,
2022-05-15
]
ic { equal(days, ^Day[3]) }datetime_add
View sourcedatetime_add[dt, period]
dt + periodAdd a Period to a DateTime
Examples:
def dt = parse_datetime["2021-01-01 01:00:00", "Y-m-d H:M:S"]
def output = datetime_add[dt, ^Year[1]]
//output> 2022-01-01T01:00:00.000Z
def output = datetime_add[dt, ^Month[13]]
//output> 2022-02-01T01:00:00.000Z
def output = datetime_add[dt, ^Hour[1000]]
//output> 2021-02-11T17:00:00.000Zdatetime_day
View sourcedatetime_day(dt, tz, d)Compute the day of the month d of a timestamp dt in the timezone tz.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
tz | String | Time zone. Must be grounded. |
d | Int | Day of the month. |
Explanation
Specifying the timezone tz is required because the day of the month, d, depends on the timezone you’re in.
Note that the timezone needs to be stated and can’t be infered.
In particular, it is not possible to infer all valid timezones tz from a given timestamp dt and day d.
Examples
Get the day of the month of a given timestamp in different timezones:
def dt = parse_datetime["2024-01-01 01:00:00", "Y-m-d H:M:S"]
def output = datetime_day[dt, "Europe/Berlin"]
//output> 1
def output = datetime_day[dt, "America/New_York"]
//output> 31
def output = datetime_day[dt, "-03:00"]
//output> 31See Also
date_day, datetime_year, datetime_month, datetime_week, and datetime_hour.
datetime_day_UTC
View sourcedatetime_day_UTC(dt, d)Compute the day of the month d of a timestamp dt assuming the UTC timezone.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
d | Int | Day of the month. |
Examples
Get the day of the month in the UTC timezone for a timestamp that is defined in the Asia/Kathmandu timezone:
def dt = parse_datetime["2024-01-01 01:45 Asia/Kathmandu", "Y-m-d H:M Z"]
def output = datetime_day_UTC[dt]
//output> 31See Also
datetime_month_UTC, datetime_week_UTC, datetime_day, and date_day.
datetime_dayname
View sourcedatetime_dayname[t, tz]Name of week-day (a string, e.g., Friday)
Example:
def t = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_dayname[t, "+03:00"] = "Friday"datetime_dayofquarter
View sourcedatetime_dayofquarter[dt, tz]Day of quarter
Example:
def t = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_dayofquarter[t, "+03:00"] = 31datetime_dayofweek
View sourcedatetime_dayofweek[dt, tz]Day of week (a number, e.g., 5 for Friday)
Example:
def dt = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_dayofweek[dt, "+03:00"] = 5
datetime_dayofweek[dt, "UTC"] = 4datetime_dayofweekofmonth
View sourcedatetime_dayofweekofmonth[dt, tz]Day of week of month, as an integer (e.g. 2 for second Friday of the month, 1 for the first Tuesday).
Example:
def t = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_dayofweekofmonth[t, "+03:00"] = 5datetime_dayofyear
View sourcedatetime_dayofyear[dt, tz]Day of year
Examples:
def dt = parse_datetime["2014-03-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_dayofyear[dt, "+03:00"] = 90
datetime_dayofyear[dt, "+00:00"] = 89datetime_daysinmonth
View sourcedatetime_daysinmonth[dt, tz]The number of days in a datetime’s month, adjusting for timezone tz.
Examples:
def t = parse_datetime["2014-02-28 23:00 +00:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_daysinmonth[t, "+03:00"] = 31
datetime_daysinmonth[t, "-03:00"] = 28datetime_hour
View sourcedatetime_hour(dt, tz, h)Compute the hour of the day h of a timestamp dt in the timezone tz.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
tz | String | Time zone. Must be grounded. |
h | Int | Hour of the day. |
Explanation
Specifying the timezone tz is required because the hour of the day, h, depends on the timezone you’re in.
Note that the timezone needs to be stated and can’t be infered.
In particular, it is not possible to infer all valid timezones tz from a given timestamp dt and hour h.
Examples
Get the hour of the day of a given timestamp in different timezones:
def dt = parse_datetime["2024-01-01 01:00:00", "Y-m-d H:M:S"]
def output = datetime_hour[dt, "Europe/Berlin"]
//output> 2
def output = datetime_hour[dt, "America/New_York"]
//output> 20
def output = datetime_hour[dt, "-03:00"]
//output> 22See Also
datetime_hour_UTC
View sourcedatetime_hour_UTC(dt, h)Compute the hour h of a timestamp dt assuming the UTC timezone.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
h | Int | Hour of the day. |
Examples
Get the hour of the day in the UTC timezone for a timestamp that is defined in the Asia/Kathmandu timezone:
def dt = parse_datetime["2024-01-01 01:45 Asia/Kathmandu", "Y-m-d H:M Z"]
def output = datetime_hour_UTC[dt]
//output> 20See Also
datetime_isleapyear
View sourcedatetime_isleapyear[dt, tz]Is it a leap year?
Examples:
def dt = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
def output = datetime_isleapyear[dt, "+03:00"]
//output> // false
def dtleap = parse_datetime["2016-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
def output = datetime_isleapyear[dtleap, "+00:00"]
//output> () // truedatetime_minute
View sourcedatetime_minute(dt, tz, m)Compute the minute part of a timestamp dt in the timezone tz.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
tz | String | Time zone. Must be grounded. |
m | Int | Minute. |
Explanation
Specifying the timezone tz is required because the minute, m, depends on the timezone you’re in.
For instance, some time zones like “Asia/Kathmandu” are shifted by 30 or 45 minutes with respect to UTC time.
Note that the timezone needs to be stated and can’t be infered.
In particular, it is not possible to infer all valid timezones tz from a given timestamp dt and minute m.
Examples
Get the minute of given timestamp in different timezones:
def dt = parse_datetime["2024-01-01 01:00:00", "Y-m-d H:M:S"]
def output = datetime_minute[dt, "America/New_York"]
//output> 0
def output = datetime_minute[dt, "Asia/Kathmandu"]
//output> 45See Also
datetime_minute_UTC
View sourcedatetime_minute_UTC(dt, m)Compute the minute m of a timestamp dt assuming the UTC timezone.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
m | Int | Minute. |
Examples
Get the minute in the UTC timezone for a timestamp that is defined in the Asia/Kathmandu timezone:
def dt = parse_datetime["2024-01-01 01:45 Asia/Kathmandu", "Y-m-d H:M Z"]
def output = datetime_minute_UTC[dt]
//output> 0See Also
datetime_month
View sourcedatetime_month(dt, tz, m)Compute the month m of a timestamp dt in the timezone tz.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
tz | String | Time zone. Must be grounded. |
m | Int | Month. |
Explanation
Specifying the timezone tz is required because the month, m, depends on the timezone you’re in.
Note that the timezone needs to be stated and can’t be infered.
In particular, it is not possible to infer all valid timezones tz from a given timestamp dt and month m.
Examples
Get the month of a given timestamp in different timezones:
def dt = parse_datetime["2021-01-01 01:00:00", "Y-m-d H:M:S"]
def output = datetime_month[dt, "Europe/Berlin"]
//output> 1
def output = datetime_month[dt, "America/New_York"]
//output> 12
def output = datetime_month[dt, "-03:00"]
//output> 12See Also
datetime_month_UTC
View sourcedatetime_month_UTC(dt, m)Compute the month m of a timestamp dt assuming the UTC timezone.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
m | Int | Month. |
Examples
Get the month in the UTC timezone for a timestamp that is defined in the Asia/Kathmandu timezone:
def dt = parse_datetime["2024-01-01 01:45 Asia/Kathmandu", "Y-m-d H:M Z"]
def output = datetime_month_UTC[dt]
//output> 12See Also
datetime_monthname
View sourcedatetime_monthname[dt, tz]The month name
Example:
def t = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_monthname[t, "+03:00"] = "January"datetime_now
View sourcedatetime_now(dt)The current time dt at the beginning of the transaction.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. |
Explanation
datetime_now is used to get current UTC time.
The resulting DateTime value reflects the start time of the current transaction.
Installed logic that makes use of datetime_now may be updated with each new transaction.
In particular, datetime_now cannot be used to capture the date and time that a model was installed.
For instance, if you install the relation def my_time = datetime_now in a model,
then each time you query def output = my_time, a new DateTime value is returned.
However, if you insert datetime_now into a base relation,
the time is preserved until a future read/write transaction updates it.
For example, def insert:my_time = datetime_now inserts the current date and time
into a base relation named my_time.
Repeatedly querying def output = my_time always returns the same DateTime value.
Examples
Get the current UTC time by simply querying for datetime_now.
Example:
def output = datetime_now
//output> 2023-10-10T18:52:35.263Zdatetime_quarterofyear
View sourcedatetime_quarterofyear[dt, tz]Quarter of the year for datetime dt, as a number between 1 and 4.
Example:
def t = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_quarterofyear[t, "+03:00"] = 1datetime_second
View sourcedatetime_second(dt, s)Compute the second s of a timestamp dt.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
s | Int | Second. |
Explanation
No timezone is required because the second, s, of a timestamp, dt, is independent of the timezone.
This is in contrast to datetime_minute and datetime_hour, where the timezone information is required.
Examples
Get the second of given timestamp:
def dt = parse_datetime["2024-01-01 01:02:03", "Y-m-d H:M:S"]
def output = datetime_second[dt]
//output> 3See Also
datetime_subtract
View sourcedatetime_subtract[dt, period]
dt - periodSubtract a Period from a DateTime, giving another DateTime.
Example:
def dt = parse_datetime["2021-01-01 01:00:00", "Y-m-d H:M:S"]
def output = datetime_subtract[dt, ^Hour[1000]]
//output> 2020-11-20T09:00:00.000Zdatetime_to_nanoseconds
View sourcedatetime_to_nanoseconds[dt]Convert datetime to nanoseconds since the epoch. Assumes dt is in UTC.
datetime_week
View sourcedatetime_week(dt, tz, w)Compute the ISO week number (opens in a new tab) w of a timestamp dt in the timezone tz.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
tz | String | Time zone. Must be grounded. |
w | Int | ISO week number. |
Explanation
Specifying the timezone tz is required because the calendar week, w, depends on the timezone you’re in.
Note that the timezone needs to be stated and can’t be infered.
In particular, it is not possible to infer all valid timezones tz from a given timestamp dt and week w.
Examples
Get the ISO week of a given timestamp in different timezones:
def dt = parse_datetime["2024-01-01 01:00:00", "Y-m-d H:M:S"]
def output = datetime_week[dt, "Europe/Berlin"]
//output> 1
def output = datetime_week[dt, "America/New_York"]
//output> 52
def output = datetime_week[dt, "-03:00"]
//output> 52See Also
datetime_week_UTC
View sourcedatetime_week_UTC(dt, w)Compute the ISO week number (opens in a new tab) w of a timestamp dt assuming the UTC timezone.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
w | Int | ISO week number. |
Examples
Get the week number in the UTC timezone for a timestamp that is defined in the Asia/Kathmandu timezone:
def dt = parse_datetime["2024-01-01 01:45 Asia/Kathmandu", "Y-m-d H:M Z"]
def output = datetime_week_UTC[dt]
//output> 52See Also
datetime_month_UTC, datetime_day_UTC, datetime_week, and date_week.
datetime_year
View sourcedatetime_year(dt, tz, y)Compute the year y of a timestamp dt in the timezone tz.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
tz | String | Time zone. Must be grounded. |
y | Int | Year. |
Explanation
Specifying the timezone tz is required because the calendar year, y, depends on the timezone you’re in.
Note that the timezone needs to be stated and can’t be infered.
In particular, it is not possible to infer all valid timezones tz from a given timestamp dt and year y.
Examples
Get the year of a given timestamp in different timezones:
def dt = parse_datetime["2021-01-01 01:00:00", "Y-m-d H:M:S"]
def output = datetime_year[dt, "Europe/Berlin"]
//output> 2021
def output = datetime_year[dt, "America/New_York"]
//output> 2020
def output = datetime_year[dt, "-03:00"]
//output> 2020See Also
datetime_year_UTC
View sourcedatetime_year_UTC(dt, y)Compute the year y of a timestamp dt assuming the UTC timezone.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | Date and time of the current transaction. Must be grounded. |
y | Int | Year. |
Examples
Get the year in the UTC timezone for a timestamp that is defined in the Asia/Kathmandu timezone:
def dt = parse_datetime["2024-01-01 01:45 Asia/Kathmandu", "Y-m-d H:M Z"]
def output = datetime_year_UTC[dt]
//output> 2023See Also
datetimes_period_milliseconds
View sourcedatetimes_period_milliseconds[dt1, dt2]The difference between two datetimes, dt2 - dt1, as a Millisecond data type.
In other words, equal to the milliseconds time period between dt1 and dt2 — which when added to dt1 gives dt2.
Example:
def output = datetimes_period_milliseconds[
unix_epoch,
parse_datetime["2021-03-19 11:00:40", "YYYY-mm-dd HH:MM:SS"]
]
ic {rel:base:Millisecond(output)}Day
View sourceDay[n]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Day constructor, ^Day, instead.
Create a period of n days.
decimal
View sourcedecimal[n, digits, v]The n-bit decimal value with digits precision from number value v.
n must be among #8, #16, #32, #64, and #128. The precision digits must be:
- between #0 and #2 if
n= #8 - between #0 and #4 if
n= #16 - between #0 and #9 if
n= #32 - between #0 and #18 if
n= #64 - between #0 and #32 if
n= #128
Note that the value v * 10^digits must be encodable with n-bits.
Examples:
decimal[#64, #2, 3.14156] = 3.14
empty(decimal[#64, #20, 1000])
empty(decimal[#8, #2, 2])decimal_bit_length
View sourcedecimal_bit_length[decimal]The bit length of a fixed-point decimal number.
Example:
def g = parse_decimal[#64, #2, "3.14"]
decimal_bit_length[g] = 64decimal_int_convert
View sourcedecimal_int_convert[x]Conversion from n-bit fixed-point decimal with d precision to n-bit int.
If the argument is not equivalent to an int, decimal_int_convert returns false.
Example:
decimal_int_convert[decimal[#32, #2, 3.00]] = 3
decimal_int_convert[decimal[#32, #2, 3.20]] = falsedecimal_precision
View sourcedecimal_precision[decimal]The precision of a fixed-point decimal number.
Example:
def g = parse_decimal[#64, #2, "3.14"]
decimal_precision[g] = 2decode_base16
View sourcedecode_base16[encoded_str]Decodes the base-16 encoded string to string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Example:
def output = decode_base16["48656C6C6F21"]
//output> "Hello!"
def output = decode_base16["E4BDA0E5A5BD"]
//output> "你好"decode_base32
View sourcedecode_base32[encoded_str]Decodes the base-32 encoded string to string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Example:
def output = decode_base32["JBSWY3DPEE======"]
//output> "Hello!"
def output = decode_base32["4S62BZNFXU======"]
//output> "你好"decode_base64
View sourcedecode_base64[encoded_str]Decodes the base-64 encoded string to string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Example:
def output = decode_base64["SGVsbG8h"]
//output> "Hello!"
def output = decode_base64["5L2g5aW9"]
//output> "你好"default_value
View sourcedefault_value[D, F, c]Make function or relation F total for domain D by defaulting to c.
The arity of F must be the arity of D + 1.
Example:
def dom = {1;2;3;4}
def f = {(1, 321); (3, 123)}
def output = default_value[dom, f, 42]
//output> (1, 321)
// (2, 42)
// (3, 123)
// (4, 42)See Also
deg2rad
View sourcedeg2rad[d]
deg2rad(d, r)Convert degrees to radians.
Parameters
| Parameter | Type | Description |
|---|---|---|
d | Float, Int | r in degrees. Must be grounded. |
r | Float | d in radians. |
Examples
Convert 180 degrees to radians:
def output = deg2rad[180]
//output> 3.141592653589793Convert -90 degrees to radians using full expression:
def output = deg2rad[-90]
//output> -1.5707963267948966denominator
View sourcedenominator[x]Denominator of a rational-like number.
Examples:
denominator[rational[64, 1, 3]] = 3
denominator[rational[64, 1, 100]] = 100
denominator[rational[64, 1, 100] + rational[64, 1, 3]] = 300
denominator[parse_decimal[#64, #2, "3.14"]] = 100
denominator[parse_decimal[#64, #5, "3.14159"]] = 10000
denominator[5] = 1describe
View sourcedescribe[R]A summary of statistics for a dataset R. R should be a relation given in the form
R(:feature_name, keys..., value). For example, data loaded using load_csv.
For each feature in the dataset, describe computes a set of statistics depending on the
data type of that feature.
For numerical data, describe computes the count, mean, standard deviation, minimum, 25th,
50th, 75th percentiles, and maximum for that feature.
For non-numerical data, describe computes the count, unique count, mode, and mode
frequency. It will also compute maximum and minimum values if the data is sortable.
If a dataset has multiple data types, it will print the numerical stats for the numerical subset, and non-numerical stats for the non-numerical subset of the data.
For example, given a dataset R in the form (produced by the CSV loader):
R = {
(:date, ^FilePos[29], 2020-01-01);
(:date, ^FilePos[60], 2020-02-02);
(:date, ^FilePos[91], 2020-03-03);
(:date, ^FilePos[127], 2020-04-04);
(:price, ^FilePos[29], 12.5);
(:price, ^FilePos[60], 14.25);
(:price, ^FilePos[91], 11.0);
(:price, ^FilePos[127], 12.25);
(:quantity, ^FilePos[29], 2);
(:quantity, ^FilePos[60], 4);
(:quantity, ^FilePos[91], 4);
(:quantity, ^FilePos[127], 3);
(:cocktail, ^FilePos[29], "martini");
(:cocktail, ^FilePos[60], "sazerac");
(:cocktail, ^FilePos[91], "cosmopolitan");
(:cocktail, ^FilePos[127], "bellini");
}describe will compute a summary:
Example:
def d = describe[R]
d[:date]
(:mode, 2020-01-01)
(:count, 4)
(:mode_freq, 1)
(:min, 2020-01-01)
(:max, 2020-04-04)
(:unique, 4)
d[:quantity]
(:max, 4)
(:count, 4)
(:std, 0.9574271077563381)
(:min, 2)
(:percentile75, 4.0)
(:percentile25, 2.75)
(:percentile50, 3.5)
(:mean, 3.25)A describe_full method is also provided, which does not aggregate over columns, and
instead computes the statistics for the whole dataset. However, describe_full may cause
errors if any unsortable data (e.g., symbols) exists in the relation.
For example, given the relation R defined above:
Example:
describe_full[R]
(:min, 32)
(:unique, 3)
(:mode, "a")
(:std, 49.47186262580647)
(:percentile25, 89.2175)
(:min, 3.27)
(:percentile50, 53.6)
(:mean, 16.75)
(:mean, 18.8675)
(:count, 7)
(:max, 72.2)
(:max, 35)
(:mode_freq, 1)despecialize
View sourcedespecialize[sv]
despecialize(sv, v)Maps a specialized value sv to the value v.
Specialized values are used for schema information. Non-specialized values are used for storing the “actual” data.
Example:
def output = despecialize[#(55)]
//output> 55
def output = despecialize[:hello]
//output> "hello"To verify the despecialization, one can write
def output = equal(despecialize[#(int[8, 0])], int[8, 0])
//output> () // truediff
View sourcediff[R, S]Set difference (complement): removes the tuples of S from R, if present.
Example:
def output = diff[{1;2;3;4} , {1;3} ]
//output> 2
// 4divide
View sourcedivide[x, y]
divide(x, y, q)
x / yDivision of two numbers.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Number | Numerator. Must be grounded. |
y | Number | Denominator. Must be grounded. |
q | Number | Quotient x / y. |
Not all numeric types can be combined with one another.
The following combinations work (note that for some type combinations, a y of zero is
mathematically undefined, so the result is false (empty)):
x | y | q |
|---|---|---|
FloatBinary | Same as x | Same as x |
Rational, FixedDecimal | Non-zero same as x | Same as x |
SignedInteger, UnsignedInteger | SignedInteger, UnsignedInteger | FloatBinary[#64] |
FloatBinary[#64] | Number | FloatBinary[#64] |
Number | FloatBinary[#64] | FloatBinary[#64] |
SignedInteger, UnsignedInteger | SignedInteger[#64] | FloatBinary[#64] |
SignedInteger[#64] | SignedInteger, UnsignedInteger | FloatBinary[#64] |
FloatBinary | SignedInteger[#64] | Same as x |
SignedInteger[#64] | FloatBinary | Same as y |
FixedDecimal | Non-zero SignedInteger, UnsignedInteger | Same as x |
SignedInteger, UnsignedInteger | Non-zero FixedDecimal | Same as y |
Rational | Non-zero SignedInteger | Rational with the larger bitsize of x and y |
SignedInteger | Non-zero Rational | Rational with the larger bitsize of x and y |
Explanation
In contrast to add and subtract, x and y need to be grounded and specified by the user.
Specifying only x and q or only y and q is not sufficient as the system can’t compute the inverse.
Examples
Divide two integers using /:
def output = 24 / 2
//output> 12.0Divide two rationals using /:
def output = rational[64, 8, 3] / rational[64, 5, 2]
//output> 16/15Divide one float by another using divide:
def output = divide[8.4, 2.1]
//output> 4.0Divide a rational by an integer using full expression:
def output(x) = divide(rational[16, 8, 3], 2, x)
//output> 4/3docstring
View sourcedocstring[:R]The docstring of a relation as a string.
Example:
doc"The number 0." def zero = 0
def output = docstring[:zero]
//output> "The number 0."domain
View sourcedomain[F]The domain of a scalar function F. The domain represents all but the last argument of F.
Example:
def output = domain[{(1, 'a', 1); (2, 'b', 4); (3, 'c', 9)}]
//output> (1, 'a')
// (2, 'b')
// (3, 'c')double_metaphone
View sourcedouble_metaphone[string_value]
double_metaphone_alt[string_value]Double Metaphone is an improvement
of metaphone that considers spelling particularities in a number of other languages.
double_metaphone and double_metaphone_alt returns an encoding of
the phonetic representation of string_value. For many strings, double_metaphone and
double_metaphone_alt returns the very same encoding. However, it may differs based on the
spelling in a non-English language.
string_value could be any arbitrary long string
Examples:
@inline def dm[string] = double_metaphone[string] ; double_metaphone_alt[string]
def output = dm["Smith"]
//output> sm0
def output = dm["Smythe"]
//output> sm0
// xmt
def output = dm["Christina"]
//output> krstn
def output = dm["Cristine"]
//output> krstn
def output = dm["I like Music"]
//output> ilkm
def output = dm["i loak Museek"]
//output> ilkm
def output = dm["RelationalAI"]
//output> rlxnl
def output = dm["rellationalleAI"]
//output> rlxnlencode_base16
View sourceencode_base16[input_str]Encodes the given string(input_str) to base16-encoded string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Examples:
def output = encode_base16["Hello!"]
//output> 48656C6C6F21
def output = encode_base16["你好"]
//output> "E4BDA0E5A5BD"encode_base32
View sourceencode_base32[input_str]Encodes the given string(input_str) to base32-encoded string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Example:
def output = encode_base32["Hello!"]
//output> "JBSWY3DPEE======"
def output = encode_base32["你好"]
//output> "4S62BZNFXU======"encode_base64
View sourceencode_base64[input_str]Encodes the given string(input_str) to base64-encoded string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Example:
def output = encode_base64["Hello!"]
//output> "SGVsbG8h"
def output = encode_base64["你好"]
//output> "5L2g5aW9"ends_with
View sourceends_with(s, suffix)True if and only if the given string, s, ends with the given suffix, suffix.
The suffix can be a string of characters or a single character.
Example:
ends_with("abc", "c") // true
ends_with("abc", 'c') // true
ends_with("abc", "abc") // true
ends_with("abc", "C") // false
ends_with("abc", "ab") // false
ends_with("abc", "abcd") // falseEntity
View sourceEntity(x)Holds if x is an entity. This is an alias for Hash.
Example:
Integrity constraint specifying that mymodule always contains an entity:
def mymodule:f = 1
ic my_entity_ic(x) { mymodule(x) implies Entity(x) }enumerate
View sourceenumerate[R]
enumerate(R, index, x...)Enumerate the tuples in the relation R from 1 to count[R].
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Relation to be enumerated. Must be grounded. |
index | Int | The new enumeration index starting at 1. |
x... | Tuples | A tuple in R associated with the new index index. |
Explanation
enumerate takes a relation R(x...) and produces a relation with the tuples (index, x...), where index is an integer running from 1 to the number of tuples in the relation (count[R]).
enumerate supports relations that contain tuples with different data type signatures.
This includes relations with tuples of various lengths, or arities. For example, {(1, 2); (1, 2, 3)} can be enumerated together.
Enumerating across data types is also supported. For example, enumerating the three tuples in {"a"; 1; 2.0} .
The enumeration is deterministic meaning enumerating the same tuples will always produce the same result.
The details of the enumeration logic are described below.
Lexicographical Order
Lexicographical order of the tuples is determined by first sorting them according to their data schema, according to the following rules:
- Tuples are first ordered by the data types in the first column, then second, and so on.
- Tuples with no data in the current column come first. For example,
(Int)comes before(Int, Int). - Within each column, types are put in alphabetical order. For example,
CharprecedesDate, which precedesFloatBinary. - If types have parameters, they are ordered by parameters. For example,
FloatBinary[#32]precedesFloatBinary[#64], and so on.
After the schemas of the tuples are sorted, the tuples with the same schema are sorted based on the actual values in the tuples, according to the following rules:
- Tuples are first sorted by the data values in the first column, then second, and so on.
- Tuples are ordered based on the intrinsic order of the data type.
- Numeric data types: Sorting numerically. For example,
1comes before2. - Text-based data types:
CharandStringare sorted “asciibetically”, which means that digits and punctuation marks come before letters, and uppercase letters come before lowercase letters; for example, “Z” precedes “a”. - Date-based data types:
DateandDateTimeare sorted so that older timestamps come first.
- Numeric data types: Sorting numerically. For example,
Examples
Enumerate an arity-1 relation:
def sample = {'a'; 'b'; 'c'}
def output = enumerate[sample]
//output> (1, 'a')
// (2, 'b')
// (3, 'c')
//first column is indexEnumerate an arity-2 relation (alphabetical on first column):
def sample = {
("phone", 45);
("laptop", 89);
("memory", 100)
}
def output(index, x...) = enumerate(sample,index, x...)
//output> (1,"laptop",89)
// (2,"memory",100)
// (3,"phone",45)Just as with aggregations, it is possible to enumerate separately per group.
In the following example, the enumeration is grouped by the group-by variable x,
which iterates over the values in the first column of sample.
def sample = { (:g, 'a'); (:g, 'b'); (:g, 'c'); (:h, 'd'); (:h, 'e'); (:h, 'f') }
def output[x] = enumerate[sample[x]]
//output> (:g, 1, 'a')
// (:g, 2, 'b')
// (:g, 3, 'c')
// (:h, 1, 'd')
// (:h, 2, 'e')
// (:h, 3, 'f')Enumerate a relation containing various tuple lengths and types:
def sample = {
2; 3;
"a"; "b";
(1, 3); (1, 10);
}
def output = enumerate[sample]
//output> (1, 2)
// (2, 3)
// (3, 1, 3)
// (4, 1, 10)
// (5, "a")
// (6, "b")Here you can see the impact of sorting the data schemas first: tuples of the form (Int) come before tuples of the form (Int, Int).
Because the sorting of data type per column is more important than the length of the tuples, the tuples of the form (String) come after (Int, Int) tuples, making ("b") the tuple with the largest index.
See Also
sort and reverse_sort.
epoch_milliseconds
View sourceepoch_milliseconds[dt]Milliseconds since Epoch time, as a value of type Int64.
eq
View sourceeq(x, y)
x = yEquality between scalar (single) values, such as integers, strings, symbols. (For equality between relations, use equal.)
Examples:
1 = 1istrue.:a = :aistrue"a" = "a"istrue2 = 2.0isfalse1 = "a"isfalse
equal
View sourceequal(R, S)
F ≡ GRelational equality. Note that eq and = should be used only for scalar values, while
equal should be used to check that two relations are the same.
erf
View sourceerf[x]The error function of x.
External link: https://en.wikipedia.org/wiki/Error_function (opens in a new tab)
Examples:
erf[2] = 0.9953222650189527
erf[-0.5] = -0.5204998778130465erfinv
View sourceerfinv[x]The inverse error function of x.
External link: https://en.wikipedia.org/wiki/Error_function#Inverse_functions (opens in a new tab)
Examples:
erfinv[0.1] = 0.08885599049425769
erfinv[-0.5] = -0.4769362762044699
erfinv[erf[1]] = 1.0escape_regex_metachars
View sourceescape_regex_metachars(string, escaped_string)Escape the necessary regular expression metacharacters in string such that
escaped_string can be used as a regular expression and have none of its
characters interpreted as metacharacters.
Example:
def ere = escape_regex_metachars["."]
def output = regex_match_all[ere, "abc.123"]will only give
{(4, ".")}since . is escaped and is not treated as a metacharacter.
export_csv
View sourceexport_csv[R]This is the main entry point to specify relations that should be
exported to CSV. The payload relation R is expected to be a
configuration relation mapping keys to relations.
Required keywords are:
:path: A string specifying the URI (location and name) where the data will be exported. Exporting to local files is not currently supported.
Optional keywords:
:data: A set of relations mapping a file position, which can be a key of arbitrary length or type, to the corresponding value. This is the data that will be exported. We expect the data relation to be of form: data(:COLUMN_NAME, pos, val):integration: A relation containing storage integration configuration.:syntax: A relation containing syntax configuration.:partition_size: An int specifying at what estimated file size in MB the produced CSV file should be split into partitions. For example, if the exported CSV file is estimated to have a size of 1GB, with:partition_size=100it will be exported into 10 partitions of roughly 100MB each. Set:partition_size=0to suppress partitioning even for very large exports at the cost of export performance. By default,:partition_size=0is used.:compression: The algorithm that is used to compress the CSV output file. We only supportgzipat the current stage.
Example using default CSV schema and syntax and exporting to Azure storage integration using a SAS token:
def integration[:provider] = "azure"
def integration[:credentials, :azure_sas_token] = "<azure_sas_token>"
def csv_data(:ORDER, pos, v) = ((1,1); (2,2); (3,3))(pos, v)
def csv_data(:LINEITEM, pos, v) = ((1,100); (2,101); (3,102))(pos, v)
def csv_data(:QUANTITY, pos, v) = ((1,2); (2,15); (3,42))(pos, v)
def export = export_csv[
(:path, "azure://<account_name>.blob.core.windows.net/container/file.csv");
(:data, csv_data)
]Example using a custom CSV schema:
def csv_syntax[:delim] = ';'
def csv_syntax[:quotechar] = '_'
def export = export_csv[
(:path, "azure://<account_name>.blob.core.windows.net/container/file.csv");
(:data, csv_data);
(:syntax, csv_syntax)
]Example with compound keys:
def csv_data(:ORDER, pos..., v) = (1, 2, 100; 2, 1, 40)(pos..., v)
def csv_data(:QUANTITY, pos..., v) = (1, 2, 10; 2, 1, 11; 3, 1, 12; 3, 2 ,13)(pos..., v)
def export = export_csv[
(:path, "azure://<account_name>.blob.core.windows.net/container/file.csv");
(:data, csv_data)
]Note that when using compound keys pos..., they are required to contain no specialized values.
This mean no RelNames like :id or any other specialized value like #(1) are allowed.
export_json
View sourceexport_json[R]This is the main entry point to specify relations that should be
exported to JSON. The payload relation R is expected to be a
configuration relation mapping keys to relations.
Required keywords are:
:path: A string specifying the location of the file that is to be created.
Optional keywords:
:data: The relation(s) that should be exported.:integration: A relation containing storage integration configuration.:indent: Number of spaces to indent the resulting document. If not present, we’ll write a compact form.
Example for a simple JSON object
def json[:author] = "David Foster Wallace"
def json[:title, :name] = "Infinite Jest"
def json[:title, :isbn] = "978-0-316-92004-9"
def export = export_json[(:path, "/path/to/file.json");
(:data, json);
(:indent, 2)]This results in the following JSON:
{
"author": "David Foster Wallace",
"title": {
"name": "Infinite Jest",
"isbn": "10: 0316921173"
}
}Since authors usually write more than one book,
we’ll make the :title path an array of objects.
Examples:
def json[:author] = "David Foster Wallace"
def titles = (1, "Infinite Jest", "978-0-316-92004-9");
(2, "The Pale King", "978-0-316-07423-0")
def json[:titles, :[], idx] = ((:name, name);
(:isbn, isbn)
from name, isbn where titles(idx, name, isbn))
def export = export_json[(:path, "/path/to/file.json");
(:data, json);
(:indent, 2)]The :[] marker, i.e. array marker, needs to be present when an array is to be correctly produced.
This yields the following output:
{
"author": "David Foster Wallace",
"titles": [
{
"name": "Infinite Jest",
"isbn": "978-0-316-92004-9"
},
{
"name": "The Pale King",
"isbn": "978-0-316-07423-0"
}
]
}factorial
View sourcefactorial[x]Factorial of x.
Defined for non-negative x.
The result is promoted to at least 64-bits.
If x is up to 64-bits, factorial is defined for values up to 20 (inclusive).
If x is Int128, factorial is defined for values up to 33 (inclusive).
If x is UInt128, factorial is defined for values up to 34 (inclusive).
filepos
View sourcefilepos[v]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the FilePos constructor, ^FilePos, instead.
Creates a FilePos representing position v in a file.
FilePos
View sourceFilePos(x)Brings the data type relation FilePos from the module rel:base into the global namespace.
For more details, see the rel:base:FilePos docstring.
filepos_value
View sourcefilepos_value[fp]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the FilePos constructor, ^FilePos, instead.
Retrieves the numeric position represented by a FilePos.
first
View sourcefirst[R]Projection to the first argument of R.
first supports heterogeneous relations, both in arity and types.
Examples:
def output = first[(1, 2, 3); (4, 5, 6)]
//output> 1
// 4
def output = first[(1, 2, 3); (4, 5); 6]
//output> 1
// 4
// 6
def output = first[("a", 1); (2, 3)]
//output> 2
// "a"FixedDecimal
View sourceFixedDecimal(nbits, ndecimals, x)Holds if x is of type FixedDecimal with a bit size of nbits and ndecimals decimal precision.
nbits and ndecimals are specialized integers.
Examples:
Integrity constraint that tests whether x is a FixedDecimal with a bit size of #64 and #4 decimal precision:
def R = decimal[#64, #4, pi_float64]
ic float_type_check(x in R) {
FixedDecimal(#64, #4, x)
}Query to check whether x is a FixedDecimal with a bit size of #64 and #4 decimal precision.
def R = {decimal[#64, #4, pi_float64]; decimal[#64, #10, pi_float64]}
def output(x) = R(x) and FixedDecimal(#64, #4, x)
//output> 3.1416FixedDecimal_spread
View sourceFixedDecimal_spread[mode, R, val]
FixedDecimal_spread(mode, R, value, x..., spread)Spread value to the tuples in relation R as decimals, either evenly or proportionally to their
weight, which is the last element in each tuple.
| Parameter | Type | Description |
|---|---|---|
mode | RelName | :even or :ratio. |
R | Relation | Source relation. Must be grounded. |
value | FixedDecimal | Decimal to be divided among tuples as spread. |
x... | Tuple | A tuple in R. |
spread | FloatBinary[#64] | Spread associated with x.... |
Explanation
FixedDecimal_spread takes a relation R(x...) and produces a relation with the
tuples (x..., spread) where the last element of each tuple (spread)
is a spread of value distributed among tuples.
When mode is :even, spread is value divided evenly among tuples.
When mode is :ratio, spread is value divided proportionally to a tuple’s
weight — the last element in each tuple.
In contrast to int_spread_by_even and int_spread_by_ratio, here spread is a decimal, 10^(-d), where d is the
number of digits used in value.
For example, if value is 3.140, the smallest unit to spread will be 0.001.
FixedDecimal_spread is empty if value is negative.
Examples
Spread 3.14 among three tuples:
def R = {("Atlanta", 50);
("Seattle", 80);
("San Francisco", 10)}
def output = FixedDecimal_spread[:even, R, decimal[#64, #3, 3.14]]
//output> Atlanta, 50, 1.047
// San Francisco, 10, 1.047
// Seattle, 80, 1.046Spread 10.5 among three tuples using :ratio:
def R = {("Atlanta", 10);
("Seattle", 80);
("San Francisco", 10)}
def output = FixedDecimal_spread[:ratio, R, decimal[#64, #3, 10.5]]
//output> Atlanta, 50, 1.05
// San Francisco, 10, 1.05
// Seattle, 80, 8.4Spread 88.55 among three tuples using full expression:
def R = {("Miles Davis", 65); ("Jimmy Smith", 76); ("Ornette Coleman", 85)}
def output(x...) = FixedDecimal_spread(:ratio, R, decimal[#64, #3, 88.55], x...)
//output> Jimmy Smith, 29.778
// Miles Davis, 25.468
// Ornette Coleman, 33.304Spread using group-by:
def R = {
("Seattle", "Washington", 1);
("San Francisco", "California", 0.4);
("Los Angeles", "California", 0.6)
}
def amount = {
("Washington", decimal[#64, #3, 50]);
("California", decimal[#64, #3, 100.0])
}
def output[state] = FixedDecimal_spread[
:ratio,
(city, v : R(city, state, v)),
amount[state]
]
//output> California, Los Angeles, 60.0
// California, San Francisco, 40.0
// Washington, Seattle, 50.0See Also
FixedPoint
View sourceFixedPoint(x)Holds if x is a fixed point number.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FixedPoint | A fixed point value. |
Explanation
A FixedPoint can be created with decimal, as shown in the examples below.
Examples
def R = decimal[#64, #4, pi_float64]
ic fixedpoint_type_check(x in R) {
FixedPoint(x)
}def R = 5; decimal[#64, #4, pi_float64]
def output(x) = R(x) and FixedPoint(x)
//output> 3.1416See Also
FixedSizeInteger
View sourceFixedSizeInteger(x)Holds if x is a fixed size integer (signed or unsigned).
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FixedSizeInteger | A fixed size integer value. |
Explanation
A FixedSizeInteger can be created with int or uint, or using an int or uint literal, as shown in the examples below.
Examples
def R = int[8, 5]; uint[8, 5]
ic fixedsize_int_type_check(x in R) {
FixedSizeInteger(x)
}def R = 5; 0x05; rational[16, -5, -7]
def output(x) = R(x) and FixedSizeInteger(x)
//output> 5; 0x05See Also
FixedSizeRational
View sourceFixedSizeRational(x)Holds if x is a fixed size rational (signed or unsigned).
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FixedSizeRational | A fixed size rational value. |
Explanation
A FixedSizeRational can be created with rational, as shown in the examples below.
Examples
def R = rational[16, -5, -7]
ic fixedsize_rational_type_check(x in R) {
FixedSizeRational(x)
}def R = int[8, 5]; uint[8, 5]; rational[16, -5, -7]
def output(x) = R(x) and FixedSizeRational(x)
//output> 5//7See Also
float
View sourcefloat[n, v]The n-bit floating point value from the number v.
n must be among 16, 32, and 64.
Examples:
float[64, 3.0] = 3.0
float[16, 3.14156] = 3.14
empty(float[11, 3.14])float_int_convert
View sourcefloat_int_convert[x]Conversion from float to int.
If the argument is not equivalent to an int, float_int_convert returns false. (See trunc_to_int, floor_to_int for general conversion.)
Example:
float_int_convert[3.0] = 3
float_int_convert[3.2] = falsefloat64
View sourcefloat64[v]The 64-bit floating point value from the number v, which must be a float.
FloatBinary
View sourceFloatBinary(#nbits, x)Holds if x is an `nbits’ floating point number.
Parameters
| Parameter | Type | Description |
|---|---|---|
#nbits | #(Int) | A specialized integer (must be a valid bit size). |
x | FloatBinary | A float value. |
Examples
Integrity constraint that tests if x is a 32-bit float (will throw if x is not a 32-bit Float):
def R = float[32, 1.321]
ic float_type_check(x in R) {
FloatBinary(#32, x)
}See Also
Float, Float32, and Float64.
Floating
View sourceFloating(nbits, x)DEPRECATED
This relation is deprecated and should be avoided. It will be removed soon.
Please use FloatBinary instead. Note that FloatBinary takes a specialized integer
for nbits.
Holds if x is an nbits' floating point number. Float(x)is a shorthand that holds ifx` is a 64-bit float.
Example:
Integrity constraint that tests if x is a 32-bit float (will throw if x is not a 32-bit Float):
def R = float[32, 1.321]
ic float_type_check(x in R) {
Floating(32, x)
}FloatingPoint
View sourceFloatingPoint(x)Holds if x is a floating point number.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatingPoint | A floating point value. |
Explanation
A FloatingPoint can be created with float or using a float literal, as shown in the examples below.
Examples
def R = float[32, 1.321]
ic float_type_check(x in R) {
FloatingPoint(x)
}def R = 5; 1.321
def output(x) = R(x) and FloatingPoint(x)
//output> 1.321See Also
floor
View sourcefloor[x]
floor(x, f)Round down to the nearest integer toward negative infinity.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Number | Number to be rounded down. Must be grounded. |
f | Number | Floor of x. |
Return type is the same as x.
Explanation
For positive x, floor rounds toward 0.
For negative x, floor rounds away from 0.
Examples
Calculate floor for decimal:
def output = floor[4.569]
//output> 4.0Calculate floor for negative decimal using full expression:
def output(f) = floor(-4.569, f)
//output> -5.0Calculate floor for positive rational:
def output = floor[rational[64, 8, 3]]
//output> 2/1See Also
floor_to_int, ceil, trunc, trunc_to_int, and round.
floor_divide
View sourcefloor_divide[x, y]
floor_divide(x, y, q)Division of two numbers, rounding the result to the nearest integer toward negative infinity.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Number | Numerator. Must be grounded. |
y | Number | Denominator. Must be grounded. |
q | Number | Largest integer less than or equal to x / y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | q |
|---|---|---|
SignedInteger[#64] | SignedInteger[#64] | SignedInteger[#64] |
SignedInteger[#64] | FloatBinary[#64] | FloatBinary[#64] |
FloatBinary[#64] | SignedInteger[#64], FloatBinary[#64] | FloatBinary[#64] |
Rational | SignedInteger[#64] | SignedInteger[#64] |
FixedDecimal | SignedInteger[#64] | Same as x |
Explanation
Largest integer less than or equal to x/y.
Computes x/y rounded towards negative infinity.
floor_divide maps the pair x, y to q, which is the floored quotient x/y.
Similar to divide and in contrast to add and subtract, x and y need to be grounded and specified by the user.
Specifying only x and q or only y and q is not sufficient, because the system can’t compute the inverse.
Is false (empty) when y = 0 for integer arguments.
Examples
Use floor division to divide a postiive integer by a positive integer:
def output = floor_divide[5, 2]
//output> 2Use floor division with full expression to divide a negative integer by a positive integer:
def output(q) = floor_divide(-5, 2, q)
//output> -3Use floor division to divide a float by an integer:
def output = floor_divide[5.1, 2]
//output> 2.0Confirm that floor_division[R] is empty when y = O:
def output = empty(floor_divide[5.1, 0])
//output> () // truefloor_to_int
View sourcefloor_to_int[x]
floor_to_int(x, f)Convert float to integer using floor.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Float | Float to be converted to integer using floor. Must be grounded. |
f | Int | Floor of x. |
Explanation
For positive x, floor_to_int rounds toward 0.
For negative x, floor_to_int rounds away from 0 toward negatve infinity.
Examples
Convert float to integer:
floor_to_int[3.1]
//output> 3Convert negative float to integer using full expression. Note that rounding goes away from 0 toward negative infinity.
def output(f) = floor_to_int(-3.1, f)
//output> -4Returns false because x is an integer:
def output = floor_to_int[3]
//output> // falseSee Also
floor, ceil, trunc, trunc_to_int, and round.
format_date
View sourceformat_date[d, format]A string where the Date d is formatted according to format.
Example:
def d = parse_date["2018-06-12", "Y-m-d"]
def output = format_date[d, "Y-mm-d"]
//output> 2018-06-12For details on the format parameter, see the Julia documentation for Dates.DateFormat (opens in a new tab).
format_datetime
View sourceformat_datetime[dt, format, tz]Format a DateTime dt, with timezone tz.
Example:
def format = "yyyy-mm-dd HH:MM ZZZ"
def dt = parse_datetime["2018-03-11 01:00 America/New_York", "Y-m-d H:M Z"]
def output = format_datetime[dt, format, "America/New_York"]
//output> "2018-03-11 01:00 EST"For details on the format parameter, see the Julia documentation for Dates.DateFormat (opens in a new tab).
formula_card_est
View sourceformula_card_est[R]The cardinality estimate of a given relational abstraction R as estimated by the
physical query optimizer. The estimate is represented as a Float. It is typically
an upper bound on the actual cardinality and can suffer from a numeric overflow, e.g. if the
formula R is a big cross-product of relations. To avoid this, use the log-version
log_card_est[R]. See log_card_est for more details.
Examples:
def card = formula_card_est[R]
def card = formula_card_est[a, b, c: R(a, b) and S(b, c) and T(a, c)]frequency
View sourcefrequency[R, elem]
frequency(R, elem, freq)
frequency[R]Find the frequency freq of elem in the set of all
last elements of tuples in the relation R.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | A general relation. Must be grounded. |
elem | Any | Element whose frequency will be found. |
freq | Number | The frequency of elem. |
Explanation
If elem is omitted, frequency[R] finds the frequency of each element.
Examples
Find the frequency of a single value:
def example = {(1, "a"); (2, "b"); (3, 123); (4, 12.5); (3, "b")}
def output = frequency[example, "b"]
//output> 2Find the frequency of all values:
def example = {(1, "a"); (2, "b"); (3, 123); (4, 123); (5, "b"); (6, "b")}
def output = frequency[example]
//output> 123, 2
// "a", 1
// "b", 3full_relation_approx_equal
View sourcefull_relation_approx_equal(tolerance, R, S)Approximate relational equality of the entire relation.
To hold true, all tuples (and the values they hold) in R and S must be approximately equal to each other.
| Parameter | Type | Description |
|---|---|---|
tolerance | SignedInteger[#64] or FloatBinary[#64] | A positive integer or float. |
R | Relation | A relation whose arguments can be compared to S. |
S | Relation | A relation whose arguments can be compared to R. |
Explanation
Two relations R and S are considered “fully relationally approximately equal” when there exists for each tuple in R a tuple in S that is considered approximately equal (and vice versa).
Two tuples are considered approximately equal if each element within one tuple is approximately equal to the element in the other tuple which is located at the same position. This implies tuples that are approximately equal need to have the same length.
See approx_eq for the details about approximate equality between two data values.
The parameter tolerance stands for the absolute tolerance and must be of type SignedInteger[#64] or FloatBinary[#64].
tolerance must be a positive number; negative numbers will return false.
full_relation_approx_equal is quite slow and should not be used for large data sets.
Example
Approximate relational equality determined as true:
def coordinates1 = (1.0, 2.0); (3.0, 6.0)
def coordinates2 = (1.0000001, 2.0); (2.9999999, 6.0000001)
def output = full_relation_approx_equal(0.001, coordinates1, coordinates2)
//output> () // trueApproximate relational equality determined as false:
def coordinates1 = (1.0, 2.0); (3.0, 6.0)
def coordinates2 = (1.0000001, 2.05); (2.9999999, 6.0000001)
def output = full_relation_approx_equal(0.001, coordinates1, coordinates2)
//output> // falseSee Also
approx_equal, approx_eq, equal, and eq.
function
View sourcefunction(R)Holds if R is a function.
| Parameter | Type | Description |
|---|---|---|
R | Relation | A general relation. Must be grounded. |
Given a relation R, function(R) is true if R is a function and false if not.
Functions are relations where values — the last elements of tuples — are uniquely determined by the keys — the initial elements of tuples.
That is, a relation R(x, y, z) is a function if and only if each initial set of elements x, y — the “key” —
map to only one value each for z.
For example, the relation {(1, “one”); (2, “two”)} is a function, but the relation
{(1, “one”); (1, “uno”); (2, “two”); (2, “dos”)} is not a function, because the keys 1 and 2 have multiple values.
Similarly, R{(1, 2, 3); (1, 3, 5)} is a function but R{(1, 2, 3); (1, 2, 4)} is not a function, because multiple tuples start with (1, 2).
This understanding of function is also consistent with mathematical functions — as with sin or power/^ — where the argument(s) of the function map to one value.
In this sense, mathematical functions are relations with a functional dependency.
The arguments, x..., and value, v, of the function map to the tuples (x..., y) in the relation.
For mathematical function, the domain of x... is usually continuous and unbound.
Examples
Evaluates to true:
def output = function({(1, 2); (2, 5)})
//output> () // trueEvaluates to false:
def output = function({(1, 2); (1, 3)})
//output> // falseArity-3 function that evaluates to true:
def output = function({(1, 2, 3) ; (1, 3, 4)})
//output> () // trueIntegrity constraint ensuring that R is a function:
ic R_is_a_function { function(R) }See Also
domain and default_value.
geometric_mean
View sourcegeometric_mean[R]
geometric_mean(R, gm)The geometric mean of the last element of each tuple in a relation R.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | A relation whose tuples contain numeric data types. Must be grounded. |
gm | SignedInteger, FloatBinary | The geometric mean of R. |
Explanation
The geometric mean of a relation R that contains n tuples is the n-th root
of the product of the last elements in each tuple.
geometric_mean aggregates over all tuples in R.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that geometric_mean groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, geometric_mean is used when the last elements of each tuple have the same type
If R is empty, geometric_mean[R] is false (empty).
Use <++ (left override) if you need a specific value for the case where R is empty.
Examples
Calculate geometric mean for R:
def R = {("A", 1); ("B", 3); ("C", 5); ("D", 7); ("E", 9)}
def output = geometric_mean[R]
//output> 3.936283427035352Calculate geometric mean for R using full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(gm) = geometric_mean(R, gm)
//output> 8.276527798701737See Also
mean, harmonic_mean, weighted_mean, mode, max, min, sum, and product.
harmonic_mean
View sourceharmonic_mean[R]
harmonic_mean(R, hm)The harmonic mean (hm) of the last elements of each tuple in a relation R.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | A relation whose tuples contain numeric data types. Must be grounded. |
hm | Number | The harmonic mean of R. |
Explanation
The harmonic mean of a relation R is the reciprocal of
the arithmetic mean of the reciprocals of the last elements in each tuple.
harmonic_mean aggregates over all tuples in R.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that harmonic_mean groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, harmonic_mean is used when the last elements of each tuple have the same type.
If R is empty, harmonic_mean[R] is false (empty).
Use <++ (left override) if you need a specific value for the case where R is empty.
Examples
Calculate the harmonic mean of R:
def output = harmonic_mean[{('a',1); ('b',2); ('a',3); ('b',4); ('c',5); ('d',6}]
2.44897959184Calculate the harmonic mean of R using the full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(hm) = harmonic_mean(R, hm)
//output> 8.229800388043014Find the harmonic mean for relation with tuples of various lengths:
def R = {(10); (2, 30); (3, 50, 2)}
def output = harmonic_mean[R]
//output> 4.736842105263158See Also
geometric_mean, weighted_mean, mean, mode, max, min, sum, and product.
hash
View sourcehash[R]
hash(R, x..., h)Hash each of the tuples in the relation and add it as a new column in the result.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Relation to be hashed. Must be grounded. |
x... | Tuples | A tuple in R associated with hash. |
h | Hash | A 128-bit HashValue index. |
Explanation
hash takes a relation R(x...) and produces a relation R(x..., h) where the last element of the relation, h, is a 128-bit HashValue
that is the result of hashing all elements in the tuple x... and combining them into one value.
hash is identical to hash128.
Examples
Hash a single value:
def output = hash['a']
//output> a, 59209653874858713274180299714158372840Hash a relation with tuples that have multiple elements:
def sample = {('a', 1); ('b', 2); ('c', 3)}
def output = hash[sample]
//output> a, 1, 218658623352236411286898175739604563355
// b, 2, 183357509907040413044473069762065340376
// c, 3, 153679601071624610141668476986592179913Hash a relation using full expression:
def sample = {('a', 1); ('b', 2); ('c', 3)}
def output(x..., h) = hash(sample, x..., h)
//output> a, 1, 218658623352236411286898175739604563355
// b, 2, 183357509907040413044473069762065340376
// c, 3, 153679601071624610141668476986592179913Confirm that identical tuples in different relations hash to the same value:
def R = (:a, 1); (:b, 2)
def S = (:a, 1); (:b, 2)
def output = equal[hash[R], hash[S]]
//output> () // trueSee Also
hash_value_uint128_convert, murmurhash3f, and murmurhash3f_with_seed.
Hash
View sourceHash(x)Holds if x is a RelationalAI HashValue generated by hash128.
Examples:
Integrity constraint that tests whether x is Hash (will throw if x is not Hash):
def R = (9, "a")
def my_hash = hash128[R]
//three value relation with hash value as third value
ic hash_type_check{
subset(my_hash, (Any, Any, Hash))
}Defines Hash as schema for a relation:
def R = (9, "a")
def my_hash = hash128[R]
def hashed_relation(x in Hash) = my_hash(_, _, x)
def output = hashed_relation
//output> -107770920621774551289984725953057040743hash128
View sourcehash128[R]
hash128(R, x..., h)Hash each of the tuples in the relation and add it as a new column in the result.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Relation to be hashed. Must be grounded. |
x... | Tuple | A tuple in R associated with hash. |
h | Hash | A 128-bit HashValue index. |
Explanation
hash128 takes each tuple x... in R and produces a relation (x..., h) where the last element of the relation, h, is a 128-bit HashValue
that is the result of hashing all elements in the tuple x... and combining them into one value.
Examples
Hash a single value:
def output = hash128['a']
//output> a, 59209653874858713274180299714158372840Hash a relation with tuples that have multiple elements:
def sample = {('a', 1); ('b', 2); ('c', 3)}
def output(x..., h) = hash128(sample, x..., h)
//output> a, 1, 218658623352236411286898175739604563355
// b, 2, 183357509907040413044473069762065340376
// c, 3, 153679601071624610141668476986592179913Hash a relation using full expression:
def sample = {('a', 1); ('b', 2); ('c', 3)}
def output(x..., h) = hash128(sample, x..., h)
//output> a, 1, 218658623352236411286898175739604563355
// b, 2, 183357509907040413044473069762065340376
// c, 3, 153679601071624610141668476986592179913Confirm that identical tuples in different relations hash to the same value:
def R = (:a, 1); (:b, 2)
def S = (:a, 1); (:b, 2)
def output = equal[hash128[R], hash128[S]]
//output> () // trueSee Also
hash_value_uint128_convert, murmurhash3f, and murmurhash3f_with_seed.
haversine
View sourcehaversine[r, x1, y1, x2, y2]
haversine(r, x1, y1, x2, y2, hs)The great circle distance of two points, and , on a sphere of radius , using the Haversine formula. The two points are specified by their latitude and longitude in radians.
Parameters
| Parameter | Type | Description |
|---|---|---|
x1 | FloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64] | coordinate of the 2D point . Must be gounded. |
y1 | FloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64] | coordinate of the 2D point . Must be gounded. |
x2 | FloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64] | coordinate of the 2D point . Must be gounded. |
y2 | FloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64] | coordinate of the 2D point . Must be gounded. |
r | FloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64] | radius of sphere. Must be grounded. |
hs | UnsignedInteger[#64], SignedInteger[#64], FloatBinary[#64] | Haversine of and on sphere of radius . |
Examples
Calculate the haversine of (10, 0) and (0, 0) on sphere of radius π/2:
def output = haversine[10, 0, 0, 0, pi_float64/2]
//output> 15.707963267948964Calculate the haversine of (10, 10) and (-10, 0) on sphere of radius 2π using full expression:
def output(hs) = haversine(10, 10, -10, 0, 2*pi_float64, hs)
//output> 7.897244441795649Hour
View sourceHour[n]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Hour constructor, ^Hour, instead.
Create a period of n hours.
iff
View sourceF iff G
F ⇔ GIf and only if (boolean equivalence), for boolean (arity 0, true or false) arguments F and G.
implies
View sourceF implies G
F ⇒ G
G ⇐ FLogical implication, for boolean (arity 0, true or false) arguments F and G.
int
View sourceint[n, v]The n-bit signed integer value from the integer value v.
n must be among 8, 16, 32, 64, and 128 and v is encodable with n-bits.
Examples:
int[8][42] = 42
empty(int[8][300])int_float_convert
View sourceint_float_convert[x]Conversion from int to float. Argument must be an int.
Example:
int_float_convert[3] = 3.0
int_float_convert[3.2] : errorint_spread_by_even
View sourceint_spread_by_even[R, value]
int_spread_by even(R, value, x..., spread)Spread value to the tuples in relation R evenly as whole units.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Source relation. Must be grounded. |
value | Int | Integer to be divided among tuples as spread. Must be grounded. |
x... | Tuple | A tuple in R. |
spread | FloatBinary[#64] | Spread associated with x.... |
Explanation
int_spread_by_even produces a relation with the tuples (x..., spread) where the last element of each tuple (spread)
is value divided equally among the tuples in R.
For example, if value is 50 and R has five tuples, spread will be 10 for each tuple.
In cases of uneven spread, as when value is 51 and R has five tuples, the remainder is distributed by units to as many tuples as possible according to their lexicographic order.
int_spread_by_even is empty if value is negative.
Examples
Spread 30 evenly over three tuples:
def R = {"apple"; "banana"; "strawberry"}
def output = int_spread_by_even[R, 30]
//output> apple, 10
// banana, 10
// strawberry, 10Spread 32 over three tuples, remainder applied to first two tuples:
def R = {"Atlanta"; "Seattle"; "San Francisco"}
def output = int_spread_by_even[R, 32]
//output> Atlanta, 11
// San Francisco, 11
// Seattle, 10Spread 45 over three tuples using full expression:
def R = {"Miles Davis"; "Jimmy Smith"; "Ornette Coleman"}
def output(x...) = int_spread_by_even(R, 45, x...)
//output> Jimmy Smith, 15
// Miles Davis, 15
// Ornette Coleman, 15See Also
int_spread_by_ratio
View sourceint_spread_by_ratio[R, value]
int_spread_by_ratio(R, value, x..., w, spread)Spread value to the tuples in relation R as whole units proportionally to their
weight, which is the last element in each tuple.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Source relation. Must be grounded. |
value | SignedInteger[#64] | Integer to be divided among tuples as spread. Must be grounded. |
x... | Tuple | A tuple in R. |
spread | FloatBinary[#64] | Spread associated with x.... |
Explanation
int_spread_by_ratio takes as input a relation R(x..., w), where x... are one or more elements that serve as the key
and w is a weight of type FloatBinary[#64] or SignedInteger[#64].
int_spread_by_ratio produces a relation with the tuples (x..., w, spread) where the last element of each tuple (spread)
is a spread among tuples, determined proportionally to a tuple’s weight as whole units.
For example, if the relation is {("X", 90); ("Y", 10)}, "X" will get 90%
of value and "Y" will get 10%.
In cases where this split results in a decimal, int_spread_by_ratio first distributes the floor value of the decimal number computed.
The remainder is distributed as single units in order starting from the
element with the highest decimal value.
int_spread_by_ratio is empty if value is negative.
Examples
Spread 100 over three tuples:
def R = {("Atlanta", 50);
("Seattle", 10);
("San Francisco", 40)}
def output = int_spread_by_ratio[R, 100]
//output> Atlanta, 50
// San Francisco, 40
// Seattle, 10
Spread 102 over three tuples with remainder:
def R = {("Atlanta", 50);
("Seattle", 10);
("San Francisco", 40)}
def output = int_spread_by_ratio[R, 102]
//output> Atlanta, 51
// San Francisco, 41
// Seattle, 10Spread 1000 over three tuples using full expression:
def R = {("apple", 17);
("banana", 18);
("strawberry", 15)}
def output(x...) = int_spread_by_ratio(R, 1000, x...)
//output> apple, 340
// banana, 360
// strawberry, 300See Also
Integer
View sourceInteger(x)Holds if x is an integer (fixed size or arbitrary precision).
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Integer | An integer value. |
Explanation
An Integer can be created with int, uint, or bigint, or with an int or uint literal, as shown in the examples below.
Examples
def R = bigint[50]; int[64, 200]; uint[8, 4]
ic int_type_check(x in R) {
Integer(x)
}def R = rational[16, -5, -7]; 5; 0x05
def output(x) = R(x) and Integer(x)
//output> 5; 0x05See Also
FixedSizeInteger, BigInteger, SignedInteger, and UnsignedInteger
is_Day
View sourceis_Day(x)DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Day(x) instead.
Note that you have to include the rel:base, because Day is the deprecated constructor.
Holds if x is a Day period.
is_Hour
View sourceis_Hour(x)DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Hour(x) instead.
Note that you have to include the rel:base, because Hour is the deprecated constructor.
Holds if x is a Hour period.
is_Microsecond
View sourceis_Microsecond(x)DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Microsecond(x) instead.
Note that you have to include the rel:base, because Microsecond is the deprecated constructor.
Holds if x is a Microsecond period.
is_Millisecond
View sourceis_Millisecond(x)DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Millisecond(x) instead.
Note that you have to include the rel:base, because Millisecond is the deprecated constructor.
Holds if x is a Millisecond period.
is_Minute
View sourceis_Minute(x)DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Minute(x) instead.
Note that you have to include the rel:base, because Minute is the deprecated constructor.
Holds if x is a Minute period.
is_Month
View sourceis_Month(x)DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Month(x) instead.
Note that you have to include the rel:base, because Month is the deprecated constructor.
Holds if x is a Month period.
is_Nanosecond
View sourceis_Nanosecond(x)DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Nanosecond(x) instead.
Note that you have to include the rel:base, because Nanosecond is the deprecated constructor.
Holds if x is a Nanosecond period.
is_Second
View sourceis_Second(x)DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Second(x) instead.
Note that you have to include the rel:base, because Second is the deprecated constructor.
Holds if x is a Second period.
is_Week
View sourceis_Week(x)DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Week(x) instead.
Note that you have to include the rel:base, because Week is the deprecated constructor.
Holds if x is a Week period.
is_Year
View sourceis_Year(x)DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Year(x) instead.
Note that you have to include the rel:base, because Year is the deprecated constructor.
Holds if x is a Year period.
json_string
View sourcejson_string[json_relation]The string representation of a relation that encodes JSON data.
Example:
def json_relation[:name] = "Amira"
def json_relation[:age] = 32
def json_relation[:height] = missing
def json_relation[:pets, :[], 1] = "dog"
def json_relation[:pets, :[], 2] = "rabbit"
def result = json_string[json_relation]results in the following JSON:
{
"name": "Amira",
"age": 32,
"height": null,
"pets": [
"dog",
"rabbit"
]
}last
View sourcelast[R]Projection to the last argument of the relation R.
last supports heterogeneous relations, both in arity and types.
Examples:
def output = last[(1, 2, 3); (4, 5, 6)]
//output> 3
// 6
def output = last[1; 2; 3]
//output> 1
// 2
// 3
def output = last[(1, 2); (3, "abc")]
//output> 2
// "abc"
def output = last[(1, 2, 3); (4, 5)]
//output> 3
// 5left_override
View sourceleft_override[R, S]
R <++ SThe (left) override operator is usually applied to relations of tuples (k..., v) with a functional
dependency from the initial (key) arguments (k...) to the last (value) argument v.
R <++ S contains all the tuples of R, plus all the tuples in S
whose key is not in R. Often, S specifies default values for keys that are missing in R.
In the result, a value in R overrides a value in S.
There are two equivalent ways to think about R <++ S:
(1) S is providing default values for keys that are missing in R.
(2) The entries in R are overriding the entries in S.
| Example | Value |
|---|---|
2 <++ 3 | 2 |
1.5 <++ 3 | 1.5 |
(1,2) <++ (1,3) | (1,2) |
(3,4) <++ (1,2); (3,5) | (1,2); (3,4) |
(3,"abc") <++ (1,2); (3,5) | (1,2); (3,"abc") |
(1,2); (3,5) <++ (3,4); (6,7) | (1,2); (3,5); (6,7) |
Override can be applied to heterogeneous relations, notably JSON-like relations. The
following examples show <++ operators applied to JSON inputs.
default_value[D, F, c]. right_override
levenshtein
View sourcelevenshtein[string1, string2]Calculate the Levenshtein distance between two strings.
Example:
levenshtein["kitten", "sitting"]
3like_match
View sourcelike_match(like_string, string)Match string with a SQL “LIKE” pattern; case-sensitive.
The % character is a wildcard, and is not escapable.
Example:
like_match("\%PROMO\%", "this is a PROMOtion")
//output> () // true
like_match(raw"%PROMO%", "this is a PROMOtion")
//output> () // truelined_csv
View sourcelined_csv[R]Given an already loaded CSV relation R, lined_csv[R] is a copy of the relation, but with the
file position field replaced with a line number. Only lines containing data, including
errors, are included in the numbering. Headers and empty lines are not counted. Thus,
line number 1 is the first non-empty, non-header line of the CSV relation.
Example:
def csv = load_csv[config]
def csv_with_lines = lined_csv[csv]load_binary
View sourceload_binary[URI_string]
load_binary[R]This is the main in-language API for loading files as binary string.
To load a file, either provide the string URI where the data resides,
or a configuration relation R that describes the data load.
The relation R, which must be an EDB or an IDB but not a formula,
can configure the data load with the following options:
Required:
:path: The path to the file, e.g."azure://<account_name>.blob.core.windows.net/container/image.jpeg".
Optional:
:integration: A relation containing storage integration configuration.
Example:
def config[:path] = "azure://<account_name>.blob.core.windows.net/container/file.bin"
def config[:integration, :provider] = "azure"
def config[:integration, :credentials, :azure_sas_token] = "<azure_sas_token>"
def output = load_binary[config]load_csv
View sourceload_csv[URI_string]
load_csv[R]This is the main in-language API for loading CSV data.
To load a CSV, either provide the string URI where the data resides,
or a configuration relation R that describes the data load.
In the first case, all columns are imported with type String.
The relation R, which must be an EDB or an IDB but not a formula,
can configure the data load with the following options:
Required: Either
:path: The path to the CSV file, e.g."azure://storage.blob.core.net/container/file.csv"Or:data: A CSV formatted string value
Optional:
:schema: A binary relation indicating the file schema. The pairs are of the form(RelName, String). The column name is specified as a Symbol (of typeRelName) and the data type asString. For example, the pair(:a, "int")indicates that column:ahas type"int". The following data types are supported:Name Type "boolean"Boolean"bool"Boolean"char"Char"date"Date"datetime"DateTime"decimal(n, digits)"FixedDecimal"float"Float"int(128)"Int128"int(64)"Int64"int"Int"sha-1"SHA1"string"String"uuid"UUID:syntax: A relation containing syntax configuration. The following options can be specified::header: A relation with(Int, RelName)pairs, specifying the column names in the file, where theIntindices indicate the column order, and the column name is provided as a Symbol (of typeRelName). This option overrides the default (or existing) header names.:header_row: AnIntthat specifies the row where the file header is. The column names are specified by the content of that row, if they are not defined using the header option above. The values -1 and 0 indicate that no header is present and the system creates column names for you.:datarow: AnIntthat specifies the row from where to start parsing values into relations.:missingstrings: One or multipleStringvalues that should be interpreted as missing values. By default, only empty fields are considered missing.:delim: An ASCIICharthat delimits individual fields while parsing. Defaults to','.:quotechar: An ASCIICharthat signals a “quoted” field while parsing. Defaults to'"'.:escapechar: An ASCIICharused to “escape” one or multiplequotecharand otherescapecharvalues within a quoted (e.g., text) field. Defaults to'\\'.:decimalchar: An ASCIICharto be used when parsing float values that separates a decimal value. Defaults to'.'.:groupmark: An ASCIIChardenoting the number grouping mark, this allows parsing of numbers that have e.g., thousand separators (like1,000.00). By default, no group marks are permitted in numbers. If:groupmarkand:delimare the sameChar, then group marks are only permitted in “quoted” numbers. For instance, if both:groupmarkand:delimare',', then the quotes around"1,000"are necessary to be processed correctly.
:integration: A relation containing storage integration configuration.
The resulting relation is of the form (column_name, file_position, value).
The file_position uniquely identifies each row in the CSV.
Examples:
Loading from literal string value:
def config[:data] = """
A,B,C
1,2,3
"""
def my_data = load_csv[config]Loading a CSV file using a constant path:
def y = load_csv["azure://<account_name>.blob.core.windows.net/container/data.csv"]
def x = y[:A, _]In the example above, all values for column :A (“A” in the original file) are stored in x.
This can also be used to only load specific columns: load_csv[path](:A, xs...).
Loading a CSV file using a configuration relation config:
def config[:path] = "/path/to/file.csv"
def config[:syntax, :delim] = '_'
def config[:syntax, :header] = (1, :A); (2, :B); (3, :C)
def config[:schema, :A] = "int"
def config[:schema, :B] = "string"
def config[:schema, :C] = "decimal(64,2)"
def csv = load_csv[config]Lastly, load_csv also supports error handling. If the CSV can’t be read (e.g. if it is
badly formatted), parsing errors are stored in the :load_errors “column”, which can be
accessed the same way as any other column. It has the format (:load_errors, file_position, error_column, raw_line).
Note : Since the arities of regular columns and the error relations differ, use the
splat operator (”…”) to make your program as resilient as possible
(cf. examples above).
See Also
export_csv, Char, int, RelName, String, Date, DateTime, decimal, FixedDecimal, and Boolean.
load_csv_row_wise
View sourceload_csv_row_wise[R]Load a CSV file into a “row-wise” relation, with the position as the first argument, and the column name second.
Included for backward compatibility, we now recommend using load_csv instead, which puts the column name first.
load_iceberg
View sourceload_iceberg[URI_string]
load_iceberg[R]Load one or multiple Apache Iceberg tables from cloud storage.
Parameters
| Parameter | Type | Description |
|---|---|---|
URI_string | String | String URI where the data resides. |
R | Relation | Configuration relation that describes the data load. Must be grounded. |
Explanation
The relation R, which must be an EDB or an IDB but not a formula,
can configure the data load with the following options:
Required:
:path: The location of the iceberg table, e.g."s3://bucket-name/path/to/table_iceberg".
Optional:
:integration: A relation containing storage integration configuration.
The result is a set of relations, one per each column in the loaded Iceberg table, with header
<[optional_prefix], column_name, row_number, value>.
Nested types (LIST, STRUCT and ARRAY) and embedded types (JSON, BSON) are not supported.
Examples
Here’s how to load a table from a private repository in S3:
def config[:path] = "s3://bucket-name/path/to/table_iceberg"
def config[:integration, :provider] = "s3"
def config[:integration, :credentials, :access_key_id] = "<access_key_id>"
def config[:integration, :credentials, :secret_access_key] = "<secret_access_key>"
def output = load_iceberg[config]See Also
load_parquet, load_csv, and load_json.
load_json
View sourceload_json[filename_or_url]
load_json[R]The relation R, which currently needs to either be an EDB or an
IDB but not a formula, can be used to configure the data load with
the following options:
Required: Either
:path: The path to the JSON file, e.g."azure://storage.blob.core.net/container/file.json"Or:data: A JSON formatted string value
Optional:
:integration: A relation containing storage integration configuration.
Examples:
Loading literal JSON values:
def data = """{"name": "Anton", "age": 56}"""
def config[:data] = data
def json = load_json[config]Loading a JSON file using a constant path:
def y = load_json["test.json"]Loading a JSON file using a configuration relation:
def config[:path] = "/path/to/file.json"
def json = load_json[config]Loading a JSON file from behind a private Azure container using a SAS token:
def config[:path] = "azure://<account_name>.blob.core.windows.net/container/file.json"
def config[:integration, :provider] = "azure"
def config[:integration, :credentials, :azure_sas_token] = "<azure_sas_token>"
def json = load_json[config]load_json_general
View sourceload_json_general[filename_or_url]
load_json_general[R]Load a JSON file using the JSON General representation. This representation does not use the
data in the JSON document to make any schema (unlike load_json). This means that arbitrary
JSON files can be loaded without scaling issues, even if the file has millions of distinct
property names.
The result consists of the following relations:
(:root, Entity): for the root of the JSON document(:child, Entity, Entity, Entity): for JSON objects and arrays, where the 1st argument is the parent, the 2nd argument is the name (for object) or index (for array) (the actual string name or index is in:value), and the 3rd is the child node.(:name, Entity): for named JSON entities.(:value, Entity, <value>): for leaf values, like strings, integers etc, where<value>is one the JSON data types (String,Int64,Float64,Bool,Missing).(:array, Entity): for JSON arrays (necessary to distinguish empty object vs array)(:object, Entity): for JSON objects
Identical sub-trees in the document use the same entity, so the result is a directed-acyclic graph (DAG). It is important to consider the shared sub-trees when analyzing the JSON document.
Examples:
A single value:
def config:data = """
"abc"
"""
def json = load_json_general[config]
with json use value, child, root
ic { root.value ≡ "abc" }A JSON array:
def config:data = """
[ "abc", "def", "ghi" ]
"""
def json = load_json_general[config]
with json use value, child, root
def index[v, x] = value(x, v) and Int(v)
ic { count[root.child] ≡ 3 }
ic { root.child[_].value ≡ ("abc"; "def"; "ghi") }
ic { root.child[index[1]].value ≡ "abc" }
ic { root.child[index[2]].value ≡ "def" }
ic { root.child[index[3]].value ≡ "ghi" }A JSON object:
def config:data = """
{ "a": 1, "b": 2, "c": 3 }
"""
def json = load_json_general[config]
with json use value, child, root
def name[s, x] = value(x, s) and String(s)
ic { count[root.child] ≡ 3 }
ic { root.child[name["a"]].value ≡ 1}
ic { root.child[name["b"]].value ≡ 2}
ic { root.child[name["c"]].value ≡ 3}load_jsonlines
View sourceload_jsonlines[filename_or_url]
load_jsonlines[R]Parse and load a JSONLines file. JSONLines is a file format that considers each line of the text file as a separate JSON object.
Example:
def data = """{"name": "Anton", "age":56}\n{"name": "Alex", "age":44}"""
def config[:data] = data
def output = load_jsonlines[config]
ic {equal(output[1,:name], "Anton")}
ic {equal(output[1,:age], 56)}
ic {equal(output[2,:name], "Alex")}
ic {equal(output[2,:age], 44)}load_jsonlines_general
View sourceload_jsonlines_general[filename_or_url]
load_jsonlines_general[R]Load a JSON Lines file using the JSON General representation. See load_json_general for a
description of the JSON General representation.
The JSON Lines file is represented identical to a JSON array. The root node is an array,
and every line is a child of this array.
As opposed to load_jsonlines, the line number is not the first argument in the result.
This makes it possible to share common sub-trees and values across documents.
load_parquet
View sourceload_parquet[URI_string]
load_parquet[R]Load one or multiple Parquet files from cloud storage.
Parameters
| Parameter | Type | Description |
|---|---|---|
URI_string | String | String URI where the data resides. |
R | Relation | Configuration relation that describes the data load. Must be grounded. |
Explanation
The relation R, which must be an EDB or an IDB but not a formula,
can configure the data load with the following options:
Required:
:path: The path to the file, e.g."s3://bucket-name/path/to/file.parquet".
Optional:
:integration: A relation containing storage integration configuration.
The result is a set of relations, one per each column in the loaded Parquet, with header
<[optional_prefix], column_name, row_number, value>.
Nested types (LIST, STRUCT and ARRAY) and embedded types (JSON, BSON) are not supported.
Examples
Here’s how to load a file from a private repository in S3:
def config[:path] = "s3://bucket-name/path/to/file.parquet"
def config[:integration, :provider] = "s3"
def config[:integration, :credentials, :access_key_id] = "<access_key_id>"
def config[:integration, :credentials, :secret_access_key] = "<secret_access_key>"
def output = load_parquet[config]See Also
load_iceberg, load_csv, and load_json.
log
View sourcelog[x, y]Logarithm of y with given base x.
Defined for non-negative x and y.
Example:
log[2, 8] = 3.0log_card_est
View sourcelog_card_est[R]The log base 2 of the cardinality estimate of a given relational abstraction R.
lowercase
View sourcelowercase[string_or_char]A string where all the characters are converted to lowercase. If a character is already lowercase or has no lowercase version, it remains unchanged.
Example:
def output = lowercase["aB1c"]
//output> "ab1c"
def output = lowercase['Â']
//output> 'â'lowercase does not take a locale option and does not handle local-specific case mapping
rules.
max
View sourcemax[R]
max(R, m)The maximum value (m) of the last element of all tuples in a relation R.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Source relation. Must be grounded. |
m | Number | The maximum of the last element of the tuples in R. |
Explanation
max aggregates over all tuples in R.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
For example, if R contains key-value pairs, max[R] finds the maximum value for R.
Note that max groups the tuples by the data type of the final numeric element.
Typically, max is used when the last elements of each tuple have the same type.
max can be used with strings.
In this case, max is determined according to lexicographical order.
For details on lexicographical ordering — particularly across data types — see enumerate.
If R is empty, max[R] is false (empty).
Use <++ (left override) if you need a specific value for the case where R is empty.
Examples
Find the maximum value of a relation’s last element:
def output = max[{(2, 3); (1, 6)}]
//output> 6Find the maximum value for each data type:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", 4.5); ("d", 6.7)}
def output = max[R]
//output> 2/5
// 6.7Find the maximum value of a relation’s last element using full expression:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", rational[64, 3, 5])}
def output(x) = max(R, x)
//output> 3/5Find the maximum value for relation with tuples of various lengths (the last element in each tuple is used to find the maximum value).
def R = { (10); (2, 30); (3, 50, 2)
}
def output = max[R]
//output> 30See Also
max_k
View sourcemax_k[k, R]
max_k(k, R, mk)The k largest values in the set of all last elements
of tuples in a relation R, excluding duplicates.
Parameters
| Parameter | Type | Description |
|---|---|---|
k | SignedInteger[#64] | Number of distinct largest values to be calculated for R. |
R | Relation | Source relation. Must be grounded. |
mk | Number | The maximum k of the last element of the tuples in R. |
Explanation
max_k identifies the k largest values in the last element of any tuple in R, excluding duplicates.
For example, if the last column contains 1, 2, 2, 3 and k = 2, then max_k[2, R] = {2; 3}.
max_k aggregates over all tuples in R.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that max_k groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, max_k is used when the last elements of each tuple have the same type.
If R contains fewer then k distinct values, then max_k will have fewer than k elements as well.
The maximum supported value for k is 10000.
If R is empty, max_k[K, R] is false (empty).
Use <++ (left override) if you need a specific value for the case where R is empty.
Examples
Determine the two largest distinct values for a relation:
def R = {(2, 3); (1, 6); (3, 5); (1, 1); (4, 1); (2, 6)}
def output = max_k[2, R]
//output> 5, 6Find the two largest distinct values in a relation using the full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(mk) = max_k(2, R, mk)
//output> 8.6
// 9.7See Also
min_k, argmin, maximum, min, argmax, sum, product, and average.
maximum
View sourcemaximum[x, y]Maximum of two arguments. The arguments should have the same type.
Examples:
maximum[3, 4] = 4
maximum[3.0, 4.0] = 4.0See Also
mean
View sourcemean[R]
mean(R, m)The arithmetic mean (m) of the last elements of each tuple in the relation R.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Source relation. Must be grounded. |
m | Number | The arithmetic mean of R. |
Explanation
mean aggregates over all tuples in R.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Note that mean groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, mean is used when the last elements of each tuple have the same numeric type.
If the relation R contains tuples with a non-numeric last element, the result may not be accurate.
If R is empty, mean[R] is false (empty).
Use <++ (left override) if you need a specific value for the case where R is empty.
Examples
Calculate the arithmetic mean of the last elements of each tuple in a relation:
def output = mean[{(2, 3); (1, 6)}]
//output> 4.5Calculate the arithmetic mean of the values in a relation using the full expression:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", rational[64, 3, 5])}
def output(m) = mean(R, m)
//output> 8/21Calculate the arithmetic mean of the values in a relation with tuples of various lengths:
def R = {(10); (2, 30); (3, 50, 2)}
def output = mean[R]
//output> 14.0Calculate the arithmetic mean of salary by department:
def salary = {("John", 126) ; ("Mary", 90); ("Paul", 117); ("Peter", 115); ("Tran", 145) }
def member = {("A", "John"); ("B", "Mary"); ("A", "Paul"); ("C" , "Peter"); ("C", "Tran") }
def department = {"A"; "B"; "C" }
def output = d in department: mean[salary[p] for p in member[d]]
//output> "A", 121.5
// "B", 90.0
// "C", 130.0See Also
geometric_mean, harmonic_mean, weighted_mean, mode, max, min, sum, and product.
median
View sourcemedian[R]
median(R, m)The median value of the last elements of each tuple in the relation R.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Source relation. Must be grounded. |
m | Number | The median of R. |
Explanation
Computes the median, or “middle” value of the set of last elements of each tuple in R.
If there are two “middle values”, then the mean of the two values is used.
For best results, tuples in R should all have the same length,
and the last element of each tuple should be a Number.
Note that, unlike other aggregations, median does not group tuples by data type.
Examples
Determine median of a relation:
def R = {("A", 7); ("B", 8); ("C", 9.7); ("D", 7.5)}
def output = median[R]
//output> 8.35Determine median of a relation using full expression:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", 4.5); ("d", 6.7); ("e", 1.2)}
def output(m) = median(R, m)
//output> 6.7Determine median salary across departments:
def salary = {("John", 126) ; ("Mary", 90); ("Paul", 117); ("Peter", 115); ("Tran", 145) }
def member = {("A", "John"); ("B", "Mary"); ("A", "Paul"); ("C" , "Peter"); ("C", "Tran") }
def department = {"A"; "B"; "C" }
def output = d in department: median[salary[p] for p in member[d]]
//output> "A", 121.5
// "B", 90.0
// "C", 130.0metaphone
View sourcemetaphone[string_value, length]metaphone returns an encoding of the phonetic representation of string_value.
metaphone lets you compare words and sentences based on how they sound in English. The
metaphone is considered as an improvement of the soundex algorithm, and does a better job
at matching words and names which sound
similar.
string_value could be any arbitrary long string.
length is the length of the encoding that is used for comparison purpose. A length of 4
is commonly used.
Examples:
def output = metaphone["Smith", 4]
//output> sm0
def output = metaphone["Smythe", 4]
//output> sm0
def output = metaphone["Christina", 4]
//output> xrst
def output = metaphone["Cristine", 4]
//output> krst
def output = metaphone["I like Music", 4]
//output> ilkm
def output = metaphone["i loak Museek", 4]
//output> ilkm
def output = metaphone["RelationalAI", 4]
//output> rlxn
def output = metaphone["rellationalleAI", 4]
//output> rlxnHere a simple illustration. Consider the following:
def my_favorite_bands = { "Metallica"; "Iron Maiden"; "Wolfheart"; "Insomium" }
def do_I_like = "Mee ta li ka"
def output = {y in my_favorite_bands : metaphone(do_I_like, 4, z), metaphone[y, 4] = z from z}the script above returns "Metallica" since since "Mee ta li ka" and "Metallica" have
the same metaphone code.
Microsecond
View sourceMicrosecond[n]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Microsecond constructor, ^Microsecond, instead.
Create a period of n microseconds.
Millisecond
View sourceMillisecond[n]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Millisecond constructor, ^Millisecond, instead.
Create a period of n milliseconds.
min
View sourcemin[R]
min(R, m)The minimum value (m) of the last element of all tuples in a relation R.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Source relation. Must be grounded. |
m | Number | The minimum of the last element of the tuples in R. |
Explanation
min aggregates over all tuples in R.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
For example, if R contains key-value pairs, min[R] finds the minimum value for R.
Note that min groups the tuples by the data type of the final numeric element.
Typically, min is used when the last elements of each tuple have the same type.
min can be used with strings.
In this case, min is determined according to lexicographical order.
For details on lexicographical ordering, see enumerate.
If R is empty, min[R] is false (empty).
Use <++ (left override) if you need a specific value for the case where R is empty.
Examples
Find the minimum value of a relation’s last element:
def output = min[{(2, 3); (1, 6)}]
//output> 3Find the minimum value for each data type:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", 4.5); ("d", 6.7) }
def output = min[R]
//output> 4.5
// 1/7Find the minimum value of a relation’s last element using full expression:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", rational[64, 3, 5])
}
def output(x) = min(R, x)
//output> 1/7Find the minimum value for a relation with tuples of various lengths (the last element in each tuple is used to find the minimum value):
def R = { (10); (2, 30); (3, 50, 2)}
def output = min[R]
//output> 2See Also
min_k
View sourcemin_k[k, R]
min_k(k, R, m)Find the k smallest values in the set of all last elements
of tuples in a relation R, excluding duplicates.
Parameters
| Parameter | Type | Description |
|---|---|---|
k | SignedInteger[#64] | The number of distinct minimum values to be calculated for R. |
R | Relation | Source relation. Must be grounded. |
mk | Number | The minimum k of the last element of the tuples in R. |
Explanation
min_k identifies the k smallest values in the last element of any tuple in R, excluding duplicates.
For example, if the last column contains 1, 2, 2, 3 and k = 2, then min_k[2, R] = {1; 2}.
min_k aggregates over all tuples in R.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that min_k groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, min_k is used when the last elements of each tuple have the same type.
If R contains fewer then k distinct values, then min_k will have fewer than k elements as well.
The maximum supported value for K is 10000.
If R is empty, min_k[k, R] is false (empty).
Use <++ (left override) if you need a specific value for the case where R is empty.
Examples
Determine the two smallest distinct values for in relation:
def R = {(2, 3); (1, 6); (3, 5); (1, 1); (4, 1); (2, 6)}
def output = min_k[2, R]
//output> 1, 3Determine the two smallest distinct values in a relation using the full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(mk) = min_k(2, R, mk)
//output> 7.5
// 8.6See Also
max_k, argmin, minimum, min, argmax, sum, product, and average.
min_max_normalization
View sourcemin_max_normalization[R]Min-Max normalization: .
Also known as min-max scaling or rescaling.
minimum
View sourceminimum[x, y]Minimum of two arguments. The arguments should have the same type.
Examples:
minimum[3, 4] = 3
minimum[3.0, 4.0] = 3.0Minute
View sourceMinute[n]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Minute constructor, ^Minute, instead.
Create a period of n minutes.
missing
View sourcemissingSingleton missing value.
Examples:
missing[] = missing
equal( (x : missing(x)) , {missing} )Missing
View sourceMissing(x)Tests whether x has the data type Missing.
The only data value that is of type Missing is missing.
Used for imported data that contain explicit nulls (such as JSON data).
Missing (with a capital) refers to the data type, while missing refers to the data.
Examples:
Query that returns all relations without missing as the second argument:
def R = { (1, 2); (3, missing) }
def output(x, y) = R(x, y) and not Missing(y)
//output> (1, 2)mode
View sourcemode[R]
mode(R, md)Find the most common value in the last element of all tuples in a relation R.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Any | Source relation. Must be grounded. |
md | Any | The mode of R. |
Explanation
If there are multiple mode values, then mode chooses the first one according to lexicographical order.
For details on lexicographical ordering — particularly across data types — see enumerate.
mode aggregates over all tuples in R whose last element is numeric.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that mode groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, mode is used when the last elements of each tuple have the same type.
If R is empty, mode[R] is false (empty).
Use <++ (left override) if you need a specific value for the case where R is empty.
Examples
Find the most common value in a relation:
def R = {(5, 8); (8, 6); (13, 12); (9, 6); (2, 9); (7, 6)}
def output = mode[R]
//output> 6
Find most common value in relation using full expression:
```rel
def R = {("A", "A"); ("B", "A"); ("C", "C"); ("D", "A"); ("E", "B");}
def output(md) = mode(R, md)
//output> "A"Find most common value in a relation with tuples of various lengths:
def R = {("A", 6, "A"); ("B", 7, "C"); ("C", "C"); ("D", "A"); ("E", "A")}
def output = mode[R]
//output> "A"model_is_function (IC)
View sourceic model_is_functionAn integrity constraint ensuring that rel:catalog:model has a functional dependency
from the name to the actual value.
modulo
View sourcemodulo[x, y]
modulo(x, y, m)Remainder after floored division.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Number | Dividend. Must be grounded. |
y | Number | Divisor. Must be grounded. |
m | Number | Remainder. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | m |
|---|---|---|
Number | Same as x | Same as x |
SignedInteger, UnsignedInteger | SignedInteger, UnsignedInteger | Type of y. Bit size is the larger of the bit sizes of x and y. |
SignedInteger[#64], FloatBinary[#64] | Number | Type of x. |
Number | SignedInteger[#64], FloatBinary[#64] | Type of y. |
FloatBinary | SignedInteger[#64] | Type of x. |
SignedInteger[#64] | FloatBinary | Type of y. |
Rational | SignedInteger[#64] | Rational[n] where n is the greater of the number of bits in x and y. |
SignedInteger[#64] | Rational | Rational[n] where n is the greater of the number of bits in x and y. |
The remainder in the division algorithm for dividing x by y using floored division for the quotient.
That is, modulo[x, y] is equivalent to x - (y * floor_divide[x, y]).
The sign of the remainder is the same as the divisor y.
If y is positive, the range is from 0 to y, inclusive.
If y is negative, range is from y to 0, inclusive.
modulo[x, y] is defined when either the types of x and y are the same, or
either operand is of type SignedInteger[#64] or FloatBinary[#64].
modulo[x, y] is false when y = 0 for integer arguments.
Examples
Compute remainder for two integers:
def output = modulo[8, 3]
//output> 2Compute remainder for two integers using full expression:
def output(m) = modulo(8, -3, m)
//output> -1Compute remainder for rational and integer:
def output = modulo[rational[64, 8, 3], 2]
//output> 2/3Confirm that modulo is empty when y = 0:
def output = empty(modulo[3, 0])
//output> () // trueMonth
View sourceMonth[n]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Month constructor, ^Month, instead.
Create a period of n months.
multiply
View sourcemultiply[x, y]
multiply(x, y, p)
x * yMultiplication of two numbers.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Number | First factor. Must be grounded. |
y | Number | Second factor. Must be grounded. |
p | Number | Product x * y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | p |
|---|---|---|
Number | Same as x | Same as x |
Rational, FixedDecimal | SignedInteger, UnsignedInteger | Same as x |
SignedInteger, UnsignedInteger | Rational, FixedDecimal | Same as y |
SignedInteger[#64] | SignedInteger[#128] | SignedInteger[#128] |
SignedInteger[#128] | SignedInteger[#64] | SignedInteger[#128] |
Number | FloatBinary[#64] | FloatBinary[#64] |
FloatBinary[#64] | Number | FloatBinary[#64] |
Explanation
In contrast to add and subtract, x and y need to be grounded and specified by the user.
Specifying only x and p or only y and p is not sufficient as the system can’t compute the inverse.
Examples
Multiply two integers using *:
def output = 24 * 2
//output> 48Multiply one float by another using multiply:
def output = multiply[8.4, 2.1]
//output> 17.64Multiply a rational by an integer using full expression:
def output(x) = multiply(rational[64, 8, 3], 2, x)
//output> 16/3See Also
murmurhash3f
View sourcemurmurhash3f[v]Hash v according to the MurmurHash3f algorithm with the default seed 0,
as a UInt128.
Equivalent to murmurhash3f_with_seed[0, v].
murmurhash3f_with_seed
View sourcemurmurhash3f_with_seed[seed in (Int64 ∪ UInt128), key]Hash key with seed via the MurmurHash3F algorithm, and yield the result as a UInt128.
The key may be any singleton value supported in Rel, (e.g. [U]Int{8,16,32,64,128},
Float{16,32,64}, Char, String, RelName, FilePos, Missing, …).
The seed must be a value in (Int64 ∪ UInt128).
Note that the standard specification for MurmurHash3F does not include 128-bit seeds, so
the result of hashing with a 128-bit seed will be different than a hash with the same value
stored in a smaller integer type (i.e. hashing with the seeds uint64[1] and uint128[1]
will result in different hashes).
This function is an implementation (in Julia) of the reference implementation of MurmurHash3F, i.e. MurmurHash3_x64_128. The original can be retrieved via:
The reference implementation was written by Austin Appleby and made public domain.
Note that this implementation departs from the standard, in order to provide different
hashes for byte-identical values of different types. While this implementation’s internals
should produce byte-identical results to the reference implementation, the primary
entrypoint here, (murmurhash3f[seed, key]) typically will not: To distinguish
byte-identical values of different types, this function mixes type information into seeds
prior to hashing.
Also note that the reference implementation supports only UInt32 seeds; for such
seeds, this implementation’s internals should provide byte-identical results.
But this implementation accepts seeds up to and including 128-bit integer types.
(For UInt32 seeds, the reference implementation initializes h1/h2,
the two UInt64s in which it accumulates/mixes the digest, with copies of seed.
This implementation does the same for UInt32 seeds, and also for all other
seed types that are less than or equal to 64 bits. For 128-bit seeds, this implementation
initializes h1 with the seed’s low bits and h2 with the seed’s high bits.)
Examples
// Without a seed
murmurhash3f["cat"] = 0x37322aa78b4b4ef4816da65505e8efaa
// With a seed
murmurhash3f_with_seed[8675309, "cat"] = 0x9fd1d18093ba94b6f454b48e58011643
murmurhash3f_with_seed[8675309, :bunny] = 0x56f800aed5ff3b7300ace61c691e7568
// byte-identical values of different types hash differently
murmurhash3f[0x01] = 0x6ed3439777f613f7df39df0849d45e09
murmurhash3f[1] = 0x9116cd3f0a651c49f1674100935b29bfNanosecond
View sourceNanosecond[n]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Nanosecond constructor, ^Nanosecond, instead.
Create a period of n nanoseconds.
nanoseconds_to_datetime
View sourcenanoseconds_to_datetime[ns]Convert nanoseconds (from the unix epoch) to datetime.
Analogous to datetime.datetime.utcfromtimestamp(seconds) in python.
Example:
nanoseconds_to_datetime[24 * 60 * 60 * 10^9]is 1970-01-02T00:00:00 (one day after unix_epoch).
num_bytes
View sourcenum_bytes[str]The number of bytes in a string value.
If a string contains Unicode characters, it’s possible that some characters take up more
than one byte, so num_bytes[str] may be larger than num_chars[str].
Example:
num_bytes["abcd"] = 4
num_bytes["中文例子"] = 12num_chars
View sourcenum_chars[str]The number of (Unicode) characters in a string, i.e. the length of the string.
A character is also known as a “Code Point” in the Unicode specification.
Example:
num_chars["abcd"] = 4
num_chars["中文例子"] = 4Number
View sourceNumber(x)Holds if x is a number (for example, Int ,Float, or their fixed-width versions).
See Also
Example:
Integrity constraint that tests whether x is of type Number (throws if x is not of type Number):
def R = {1; 1.5; uint[8,3]; 4; float[32, 1.321]}
ic number_ic { subset(R, Number) }numerator
View sourcenumerator[x]Numerator of a rational-like number.
Examples:
numerator[rational[64, 1, 3]] = 1
numerator[rational[64, 1, 100]] = 1
numerator[rational[64, 1, 100] + rational[64, 1, 3]] = 103
numerator[parse_decimal[#64, #2, "3.14"]] = 314
numerator[parse_decimal[#64, #5, "3.14159"]] = 314159
numerator[5] = 5pack
View sourcepack(x₁, ..., xₙ, v)Creates a packed structure v storing the values (x₁, ..., xₙ) in sequence.
pack cannot be used with point-free syntax.
Direct usage of pack should be avoided, as it serves primarily as a low-level
interface for value types.
parse_date
View sourceparse_date[d, format]Parse Date.
This function is only defined for a valid combination of date string
d and format string format, and invalid arguments will evaluate
to false (the empty relation, {}).
Examples:
def output = parse_date["2018-06-12", "Y-m-d"]
//output> 2018-06-12For details on the format parameter, see the Julia documentation for Dates.DateFormat (opens in a new tab).
parse_datetime
View sourceparse_datetime[date_string, format]
parse_datetime(date_string, format, date)Parses datetime information (date_string) given a date-time format (format).
Parameters
| Parameter | Type | Description |
|---|---|---|
date_string | String | A string with date and time information formatted according to format. Must be grounded. |
format | String | A valid date-time format. Must be grounded. |
date | DateTime | A DateTime object containing the parsed date and time information. |
Explanation
The form parse_datetime[date_string, format] can be used to create the Datetime value (date).
The form parse_datetime(date_string, format, date) can be used to check that date maps to date_string given the date-time format format.
parse_datetime evaluates to false if date_string or format is invalid.
Parameters for DateTime Format Strings
| Parameter | Example | Description |
|---|---|---|
| y | 2024 | Matches year. |
| m | 1, 01 | Matches 1 or 2-digit months. |
| d | 1, 01 | Matches 1 or 2-digit days. |
| H | 00 | Matches hours (24-hour clock). |
| I | 00 | For outputting hours with 12-hour clock. |
| M | 00 | Matches minutes. |
| S | 00 | Matches seconds. |
| s | .500 | Matches milliseconds. |
| e | Mon, Tues | Matches abbreviated days of the week. |
| E | Monday | Matches full name days of the week. |
| p | AM | Matches AM/PM (case-insensitive). |
| yyyymmdd | 19960101 | Matches fixed-width year, month, and day. |
| z | +04:00, +0400, UTC+4 | Matches a numeric UTC offset. |
| Z | Asia/Dubai, UTC | Matches names of time zones from the TZ database. |
| u | Jan | Matches abbreviated months according to the _locale_keyword. |
| U | January | Matches full month names according to the _locale_keyword. |
Examples
Parse a string with date and time information:
def output = parse_datetime["2022-03-01 02:21:09", "y-m-d H:M:S"]
//output> 2022-03-01T02:21:09.000ZParse a string with date and time (incl. milliseconds) information:
def output(x) = parse_datetime("2024-01-15 00:00:00.003","y-m-d H:M:S.sss", x)
//output> 2024-01-15T00:00:00.003ZParse a string with timezone information:
def output = parse_datetime["2018-03-11 01:00 America/New_York", "Y-m-d H:M Z"]
//output> 2018-03-11T06:00:00.000Zwhere the time-zone name must match the names in the time-zone (tz) database.
See Also
string, parse_int, parse_float, and parse_date.
parse_decimal
View sourceparse_decimal[bits, precision, string]Parse a string representation of a fixed-point decimal number to a decimal[bits, precision]
The implementation does not consider a locale. The decimal separator is always . and
the thousands separator is always ,. The thousands separator is optional.
If the string has more digits after the decimal point than supported by the precision
parameter, then the number is rounded to the nearest number.
This function is only defined for valid arguments. For invalid arguments it will be false (the empty relation, {}).
Examples:
parse_decimal[#64, #2, "3.14"]
FixedDecimal{Int64,2}(3.14)
parse_decimal[#64, #1, "4.27"]
FixedDecimal{Int64,1}(4.3)
parse_decimal[#64, #2, ""]
FixedDecimal{Int64,2}(0.00)
parse_decimal[#64, #2, "1,234.567"]
FixedDecimal{Int64,2}(1234.57)
parse_decimal[#64, #2, "invalid"]
{}parse_float
View sourceparse_float[string]Parse a string representation of a float to a FloatBinary[#64]
Note that this currently does not consider a locale (decimal separator is always .)
Is false (empty) if the string fails to parse as an integer.
Examples:
parse_float["3.14"] = 3.14
parse_float["3"] = 3.0
empty(parse_int["hello"])parse_int
View sourceparse_int[string]Parse a string representation of an integer to a SignedInteger[#64]
Is false (empty) if the string fails to parse as an integer.
Example:
parse_int["123"] = 123
empty(parse_int["hello"])parse_int128
View sourceparse_int128[string]Parse a string representation of an integer to a SignedInteger[#128]
Is false (empty) if the string fails to parse as an integer.
Example:
parse_int128["9223372036854775808"] = 9223372036854775808
empty(parse_int["hello"])parse_json
View sourceparse_json[json_string_value]Parses a JSON value directly from a string.
Example:
def json = parse_json["""{"name": "Anton", "age": 56}"""]parse_json_general
View sourceparse_json_general[json_string_value]Parse a JSON document directly from a string using the JSON General representation. See
load_json_general for a description of the JSON General representation.
Example:
def json = parse_json_general["123"]
with json use value, child, root
ic { root.value ≡ 123 }parse_jsonlines
View sourceparse_jsonlines[jsonlines_string_value]Parse a JSON Lines file directly from a string.
The result of parse_jsonlines is an Int64 line number followed by the Rel representation
of the JSON document as in load_json.
Example:
def output = parse_jsonlines["""
{"name": "Luca", "age": 44}
{"name": "Kai", "age": 23}
{"name": "Harper", "age": 21}
"""]
ic { equal(count[output], 6) }
ic { equal(output[1, :name], "Luca") }
ic { equal(output[2, :name], "Kai") }
ic { equal(output[3, :name], "Harper") }parse_jsonlines_general
View sourceparse_jsonlines_general[json_string_value]Parse a JSON Lines file directly from a string using the JSON General representaiton. See
load_json_general for a description of the JSON General representation.
The result of parse_jsonlines_general has the same representation as
load_jsonlines_general.
parse_uuid
View sourceparse_uuid[str]Parse a UUID string (in the standard 8-4-4-4-12 format) to a UInt128 value.
Example:
parse_uuid["22b4a8a1-e548-4eeb-9270-60426d66a48e"] = 0x22b4a8a1e5484eeb927060426d66a48ePattern
View sourcePattern(x)Holds if x is of type Pattern, which is a compiled regular expression (see regex_compile).
Example:
Integrity constraint that tests whether x is of type Pattern:
def R = regex_compile["a.*b"]
ic pattern_ic(x in R) {
Pattern(x)
}pattern_match
View sourcepattern_match(pattern, string)Match string with a pattern (pre-compiled regular expression)
Example:
def p = regex_compile["^.*@.*$"]
def output = pattern_match(p, "foo@example.com")
//output> () // truepercentile
View sourcepercentile[R, p]Select the element of R corresponding to the p-th percentile, computed with linear
interpolation.
If the p-th percentile does not correspond to a single element, then
percentile_continuous computes a weighted average of the two values surrounding the
p-th percentile.
There are a number of different approaches for computing linearly interpolated percentiles.
Here, the rank of the percentile is computed by x = p(N - 1) + 1, which corresponds to
the C = 1 variant in https://en.wikipedia.org/wiki/Percentile (opens in a new tab). This is also the approach
used in Julia’s libraries and NumPy.
Note that percentile is not defined for p <= 0 or p > 100.
Example:
def output = percentile[{(1, 12); (2, 24); (3, 16)}, 60]
//output> 17.6percentile_nearest
View sourcepercentile_nearest[R, p]Select the element of R corresponding to the p-th percentile.
The p-th percentile is the smallest value in the list such that no more than p percent of
the data is strictly less than the value and at least p percent of the data is less than
or equal to that value (nearest-rank method in https://en.wikipedia.org/wiki/Percentile (opens in a new tab)).
This function computes the p-th percentile based on ranking the last argument of R.
Note that percentile_nearest is not defined for p <= 0 or p > 100.
Example, here 33% of the values are strictly less than 16, and 66% of the values are less than or equal to 16, so the 60-th percentile is 16:
def output = percentile_nearest[{(1, 12); (2, 24); (3, 16)}, 60]
//output> 16period_add
View sourceperiod_add[period1, period2]Add two periods. For now, they need to be of the same type.
def output = period_add[Minute[3], Minute[4]]
//output> 7period_day_to_int
View sourceperiod_day_to_int[day]Conversion from period Day to int.
In other words, returns the value of Day data type as an integer.
Example:
def num_of_days = period_day_to_int[^Day[3]]
ic { equal(num_of_days, 3) }period_max
View sourceperiod_max[period1, period2]Maximum of two periods. The result is expressed as a nanosecond period.
Example:
def output = period_max[Minute[3], Minute[4]] = Minute[4]
//output> () // trueperiod_min
View sourceperiod_min[period1, period2]Minimum of two periods. The result is expressed as a nanosecond period.
Example:
def output = period_min[Minute[3], Minute[4]] = Minute[3]
//output> () // truepivot
View sourcepivot[T]
pivot(T, tuple_position, value)Pivot a relation T.
The pivoted relation has the form (tuple_position, value), where tuple_position is the tuple position of each element within T and value is its corresponding value.
Parameters
| Parameter | Type | Description |
|---|---|---|
T | Relation | Source relation. Must be grounded. |
tuple_position | Int | The position of the element value within T. |
value | Any | An individual element within T. |
Explanation
If a relation is seen as a table, then pivot rotates the table, such that columns in the relations become rows.
Each row in the rotated relation is prefixed with its column position.
The relation pivot in Rel performs a transformation that is known in other systems often as unpivot or melt.
More precisely, pivot maps a relation T to a binary relation that contains all elements in T which are keyed by their tuple position(s) in T.
That is, pivot[(t1, ..., tn)] maps to the relations {(1, t1);... (n, tn)}.
If a relation has three elements, for example, pivot keys first elements with 1, second elements with 2 ,and third elements with 3.
pivot will work for relations with many tuples, even if the tuples do not have the same arity.
That is, the table need not be “rectangular” for pivot to work.
pivot[true] and pivot[false] are both false (the empty relation).
Examples
Pivot an arity-4 relation using shorthand:
def output = pivot[(5, 60, 7, 2.0)]
//output> (1, 5)
// (2, 60)
// (3, 7)
// (4, 2.0)Pivot mixed-arity relation using full expression:
def employees = {
("jane", 42, "engineering");
("tran", 24)
}
def output = x... : pivot(employees, x...)
//output> 1, jane
// 1, tran
// 2, 24
// 2, 42
// 3, engineeringIf relation R is unary, pivot[R] will turn it into a binary relation where the first element of each tuple is 1.
def output = pivot[{5; 6}]
//output> 1, 5
// 1, 6pop_standard_deviation
View sourcepop_standard_deviation[R]
pop_stddev[R]Population standard deviation
pop_zscore_normalization
View sourcepop_zscore_normalization[R]Z-score normalization (population) of (the last argument of) the relation R.
power
View sourcepower[b, n]
power(b, n, e)
b ^ nExponentiation of b to the power of n.
Parameters
| Parameter | Type | Description |
|---|---|---|
b | Number | Base. Must be grounded. |
n | Number | Exponent. Must be grounded. |
e | Number | Exponentiation b ^ n. |
Not all numeric values can be mixed with each other. The following combinations are valid:
b | n | e |
|---|---|---|
Number | SignedInteger[#64] | Same as b |
SignedInteger[#64], FloatBinary[#64] | FloatBinary[#64] | FloatBinary[#64] |
BigInteger | BigInteger | BigInteger |
When both b and n are integer types, n cannot be negative.
When b is negative, n must have an integer value like 2, -3, or 4.0.
The data type of n doesn’t need to be integer. Floating point numbers are also allowed as long as their value represents an integer number.
Examples
Using only positive integers ensures the result is an integer too:
def output = 2 ^ 8, power[5, 2]
// output> 256, 25One can also mix integer and floating-point numbers:
def output = power(3.0, 2, 9.0)
//output> () // trueHowever, the exponent needs to have an integer value when the base is negative:
def output = (-10)^-4.0
// output> 0.0001prefix_join
View sourceprefix_join[R, S]
R <: SThe prefix join (or restriction) of S to R consists of the tuples (x..., y...) in S where the prefix (x...) is in R.
That is, R <: S contains the tuples in S that have a prefix in R.
| Example | Normalized |
|---|---|
n <: edge | x, y: edge(x, y) and x = n |
female <: parent | x, y: female(x) and parent(x, y) |
t <: players | x, p: players(x, p) and t = x |
t.players <: age | p, v: players(t, p) and age(p, v) |
intern <: salary | p, v: intern(p) and salary(p, v) |
The restriction operator can also be used to select subsets of JSON-like relations:
-
:a <: jsonwherejsonis{"a": {"b": 1, "c": 2}, "d": 3}has value{"a": {"b": 1, "c": 2}} -
(:[], _, :a) <: jsonwherejsonis[ {"a": 1, "b": 2}, {"a": 3, "b": 4} ]has value[ {"a": 1}, {"a": 3} ].
product
View sourceproduct[R]
product(R, p)The product (p) of the last element of all tuples in a relation R.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | A relation whose tuples contain numeric data types. Must be grounded. |
p | Number | The product of the last element of the tuples in R. |
Explanation
product aggregates over all tuples in R whose last element is numeric.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
For example, if R contains key-value pairs, product[R] finds the product of values for R.
Note that product groups the tuples by the data type of the final numeric element.
Typically, product is used when the last elements of each tuple have the same type.
If R is empty, product[R] is false (empty).
Use <++ (left override) if you need a specific value for the case where R is empty.
Examples
Find the product of a relation’s last element:
def output = product[{(1, 4); (2, 5)}]
//output> 20Calculate the product for each data type:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", 4.5); ("d", 6.7)}
def output = product[R]
//output> 30.150000000000002
// 2/35Calculate the product of a relation’s last element using full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(p) = product(R, p)
//output> 4692.375Calculate the product of relations whose last elements are rationals:
def R = {("A", rational[64, 8, 3]); ("B", rational[64, 9, 7]); ("C", rational[64, 11, 4]); ("D", rational[64, 8, 3])}
def output = product[R]
//output> 176/7See Also
proper_subset
View sourceproper_subset(R, S)
R ⊂ SR is a proper subset of S if subset(R, S) and R and S are not equal. This means
there has to be at least one fact in S that is not in R.
rad2deg
View sourcerad2deg[r]
rad2deg(r, d)Convert radians to degrees.
Parameters
| Parameter | Type | Description |
|---|---|---|
r | Float, Int | d in radians. Must be grounded. |
d | Float | r in degrees. |
Examples
Convert -π/2 to degrees:
def output = rad2deg[-pi_float64/2]
//output> -90.0Convert π to degrees using full expression:
def output(d) = rad2deg(pi_float64, d)
//output> 180.0random_mersenne_twister
View sourcerandom_mersenne_twister[seed, R]Generates a pseudorandom number for every tuple in R using the Mersenne Twister PRNG.
random_mersenne_twister takes a relation R(xs...) and produces a relation with the
tuples (xs..., r) where r is a pseudorandom number generated by using the Mersenne
Twister algorithm with the given seed. The value r is a Float64 in the range of [0, 1].
The seed is required to be a number convertible to an unsigned 128-bit integer (UInt128)
or a DateTime. For a seed dt of type DateTime the value of epoch_milliseconds[dt] is
used as seed.
Please note that if seed has more than one value, then the smallest value in seed will
be used as the seed (according to the native sort order that is used by sort). If seed
is empty, then the result is empty.
Example:
def output = random_mersenne_twister[0, true]
//output> (0.8236475079774124,)
def output = random_mersenne_twister[random_uint128, 'a']
//output> ('a', 0.590845)
def sample = {'a'; 'b'; 'c'}
def output = random_mersenne_twister[random_uint128, sample]
//output> ('a', 0.590845)
// ('b', 0.766797)
// ('c', 0.566237)
def output = random_mersenne_twister[datetime_now, true]
//output> (0.09946255273771532,)random_threefry_float64
View sourcerandom_threefry_float64[key1, key2]Generates a pseudorandom number of type Float64 between 0.0 and 1.0 using the Threefry algorithm.
The Threefry algorithm depends on two keys: key1 and key2 of type UInt64 or Int64.
One key can be used as the seed. The other key can be used as the stream position.
Which key is used for what is up to the user.
Examples:
Getting a single random Float64 number:
def output = random_threefry_float64[1234, 1]
//output> 0.14708645730224323Generating a sequence of random Float64 numbers using a user-specific seed:
def output = random_threefry_float64[1234, i] for i in range[1, 3, 1]
//output> (1, 0.14708645730224323)
// (2, 0.18124311325337028)
// (3, 0.14463837673485513)Using a randomly generated (but deterministic) seed via random_threefry_uint64:
def seed = random_threefry_uint64[1234, 0]
def output = random_threefry_float64[seed, i] for i in range[1, 3, 1]
//output> (1, 0.2959011588531637)
// (2, 0.5971368640131505)
// (3, 0.4259318598026802)Generating a random Float64 number from the indeterministic random seed random_uint64:
def output = random_threefry_float64[random_uint64, 0]random_threefry_uint64
View sourcerandom_threefry_uint64[key1, key2]Generates a pseudorandom number of type UInt64 using the Threefry algorithm.
The Threefry algorithm depends on two keys: key1 and key2 of type UInt64 or Int64.
One key can be used as the seed. The other key can be used as the stream position.
Which key is used for what is up to the user.
Note that the output of random_threefry_uint64 can be used as a key again in a subsequent call.
This capability allows the user to start a new random sequence from a previous sequence without
the need to track which keys have already been used.
Examples:
Getting a single random UInt64 number:
def output = random_threefry_uint64[1234, 1]
//output> 0xbf025a77543cc31dGenerating a sequence of random UInt64 numbers:
def output = random_threefry_uint64[1234, i] for i in range[1, 3, 1]
//output> (1, 0xbf025a77543cc31d)
// (2, 0xe532e65f2dc0c673)
// (3, 0x1bb25070549d29e7)Generating two sequences of random UInt64 numbers by creating a new seed from the previous seed:
def seed1 = random_threefry_uint64[1234, 0]
def seed2 = random_threefry_uint64[seed1, 0]
def output:one = random_threefry_uint64[seed1, i] for i in range[1, 3, 1]
def output:two = random_threefry_uint64[seed2, i] for i in range[1, 3, 1]
//output> (:one, 1, 0x2ca4bc02da81f726)
// (:one, 2, 0x12898ddf6262c27b)
// (:one, 3, 0xd606d09ded02d4dd)
// (:two, 1, 0x48879dd755a393be)
// (:two, 2, 0xc5683a27c1e876a7)
// (:two, 3, 0xfdb025894557c350)random_uint128
View sourcerandom_uint128Random number generated using the random device. It is an unsigned 128-bit integer.
A single random number is generated using the random device of the operating system for every transaction. Within the transaction, the random number does not change. The random number can be used as the seed of a pseudo-random number generator.
Examples:
def output = random_uint128
//output> (0x648fa1de9056c1c7de7fc61bc138f5a8,)Please note that random numbers need to be used with caution in views that need to be materialized or even incrementally maintained. If a view depends on a random number, then it needs to be recomputed every time the view is needed because the random number changes with every transaction and the view is always be consistent with its inputs.
If a random seed should not change with every transaction, then the state of a seed should be managed explicitly as an EDB. For example, a seed uses for a PRNG can be initialized in one transaction and then the same value is used from that point. In this way, materialized views involving random numbers can be reused.
random_uint64
View sourcerandom_uint64Random number generated using the random device. It is an unsigned 64-bit integer.
This is a truncation of random_uint128 to the lower 64 bits. It does not provide an
additional source of random numbers.
Please check out the documentation for random_uint128 to get more information about how to
use random numbers in various situations.
Example:
def output = random_uint64
//output> (0xde7fc61bc138f5a8,)range
View sourcerange[start, stop, step]
range(start, stop, step, x)Generate a relation with integer values between start and stop, inclusive, advancing by step each time.
Parameters
| Parameter | Type | Description |
|---|---|---|
start | Int[b], UInt[b], Float | Starting point for range (inclusive). Must be grounded. |
stop | same as start | Ending point for range (inclusive). Must be grounded. |
step | same as start | Step size. Positive integer. Must be grounded. |
x | same as start | Result of range. |
b can be 8, 16, 32, 64, or 128.
Explanation
range produces a one-column relation containg the values start, start + step, start + 2*step and so on as long as the values don’t exceed the value defined by stop.
That is, if start <= stop and step > 0, then range[start, stop, step] has all the values
x = start + i * step <= stop for non-negative integers i.
Can be used to generate a sequence of numbers.
step must be a positive integer.
If start > stop or step <= 0, then range[start, stop, step] is empty.
Examples
Generate a sequence of numbers from 2 to 10, incrementing by 2:
def output(x) = range(2, 10, 2, x)
//output> 2
// 4
// 6
// 8
// 10Generate a sequence of numbers from 0 to 6, incrementing by 1.2:
def output = range[0.0, 6.0, 1.2]
//output> 0.0
// 1.2
// 2.4
// 3.6
// 4.8
// 6.0rational
View sourcerational[n, num, denom]The n-bit rational value from integer numerator num and denominator denom.
Both num and denom must be encodable with n-bits.
The result is invalid when both the numerator and the denominator are zero.
Rational
View sourceRational(nbits, x)Holds if x is an nbits rational.
Example:
Query that checks that x is of type Rational with a bit size of nbits, a numerator of -5, and a denominator of -7:
def my_rational = rational[16, -5, -7]
def output(x) = my_rational(x) and Rational(16, x)
//output> 5/7rational_convert
View sourcerational_convert[n, x]Convert a number x to a rational with n-bit integer representation.
Any type that supports numerator and denominator is supported.
Examples:
rational_convert[64, 3] = (3//1,)
rational_convert[64, decimal[#64, #2, 0.75]] = (3//4,)RationalNumber
View sourceRationalNumber(x)Holds if x is a rational number.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | RationalNumber | An integer value. |
Explanation
A RationalNumber can be created with rational, as shown in the examples below.
Examples
def R = rational[16, -5, -7]
ic rational_type_check(x in R) {
RationalNumber(x)
}def R = int[8, 5]; uint[8, 5]; rational[16, -5, -7]
def output(x) = R(x) and RationalNumber(x)
//output> 5//7See Also
regex_compile
View sourceregex_compile(regex, pattern)Compile a regular expression to a pattern. If regex is a pattern, rather than a string,
then pattern = regex.
Example:
def p = regex_compile["^.*@.*$"]
pattern_match(p, "foo@example.com")
//output> () // trueregex_match
View sourceregex_match(regex, string)Match string with a regular expression (string or pattern).
Note that if the entire string needs to be matched, then a leading ^ and
trailing $ are required in the regular expression.
Example:
regex_match("^.*@.*$", "a@b")regex_match_all
View sourceregex_match_all[regex, input_string]All the occurrences of a regular expression regex (string or pattern)
in string, including all the matches and offsets.
Each match is a pair (i, s) with the character index i where that matching string starts and
the matching string s.
Example:
regex_match_all["(?<hour>\\d+):(?<minute>\\d+)",
"Appointment from 12:45 to 1:30"]is equal to
{(19, "12:45"); (28, "1:30")}rel:catalog:model (bound)
View sourcebound rel:catalog:modelDeclare that rel:catalog:model has type (String, String).
This declaration generates an IC ensuring that rel:catalog:model contains
only tuples of type (String, String).
rel:catalog:model_creation_time (bound)
View sourcebound rel:catalog:model_creation_timeDeclare that rel:catalog:model_creation_time has type (String, DateTime).
This declaration generates an IC ensuring that rel:catalog:model_creation_time contains
only tuples of type (String, DateTime).
rel:catalog:model_update_time (bound)
View sourcebound rel:catalog:model_update_timeDeclare that rel:catalog:model_update_time has type (String, DateTime).
This declaration generates an IC ensuring that rel:catalog:model_update_time contains
only tuples of type (String, DateTime).
rel:integration:load_partitioned_csv
View sourcerel:integration:load_partitioned_csv[URI_string]
rel:integration:load_partitioned_csv[R]This is the main in-language API for loading partitioned CSV data into a single logical relation.
For detailed information on CSV loading, see load_csv.
To load a partitioned CSV, specify the following:
:path: The path to the first CSV partition, e.g."azure://storage.blob.core.net/container/file_1_of_24.csv". For more than one partition to get picked up, please note the naming schema: Name partitions using[...]_m_of_n[...], wheremis the current partition andnthe total number of partitions (e.g.mycsv_1_of_16.csv,mycsv_2_of_16.csv, etc.).- Only the first partition should include header information.
- Make sure all partitions are stored under the same
:pathprefix.
The resulting relation is of the form (column_name, partition, line, value). partition, line uniquely identifies each row in the CSV.
If errors occur, the resulting relation is of the form (:load_errors, partition, line, error_column, raw_line).
partition and line are UInt32s. To address them, please use uint[32, <number>].
If only a single partition is provided or data is directly passed into the load, the
resulting relation looks just like a load_csv call with an added partition = uint[32, 1].
rel:mirror:argument
View sourcerel:mirror:argument[T]
rel:mirror:argument(T, tuple_position, value)Maps the arguments of a relation T to a new binary relation containing all the elements of T keyed by their position in the argument tuple.
Examples
Pivot an arity-3 relation:
def output = rel:mirror:argument[{"first", "second, "third"}]
//output> (#1, "first")
// (#2, "second")
// (#3, "third")rel:mirror:arity
View sourcerel:mirror:arity[R]
rel:mirror:precise_arity[R](v)The specialized form of the arity of a relation.
rel:mirror:precise_arity[R] is similar to rel:mirror:arity[R] but only outputs the arities for which there are run-time values in R.
Example:
def p = (1, 2, 3)
ic { rel:mirror:arity[p] = #3 }
ic { rel:mirror:precise_arity[p] = #3 }
def q = p ∩ (4, 5, 6) // empty
ic { rel:mirror:arity[q] = #3 }
ic { not exists(rel:mirror:precise_arity[q]) }RelName
View sourceRelName(x)Holds if x is a relation name.
Examples:
Integrity constraint specifying that mymodule always contains a RelName and an integer:
def mymodule:f = 1
ic { subset(mymodule, (RelName, Int)) }
def output = mymodule
//output> (:f, 1)relname_string
View sourcerelname_string[my_relname]
relname_string(my_relname, my_string)Convert RelName (my_relname) data into String data (my_string).
Parameters
| Parameter | Type | Description |
|---|---|---|
my_relname | RelName | A valid RelName. |
my_string | String | A valid string. |
Explanation
The relation relname_string maps a RelName value to its corresponding String value.
RelName is a specialized data type version of the String data type.
RelName data types are used for metadata information.
Relation, module, and IC names are all stored as RelName.
relname_string can be used to:
- Verify that a RelName and string match.
relname_string(relation_name, string)evaluates totrueifrelation_namematchesstring. Ifrelation_namedoes not matchstring,relname_string(relation_name, string)evaluates tofalse(the empty relation,{}). - Convert a RelName to a string (
relname_string[relation_name]provides shorthand for this use).
Using relname_string to convert a String to a RelName is not yet supported.
Examples
Verify that a RelName matches a string.
relname_string(:rel, "rel")
//evaluates to `true` because the RelName `:rel` matches the string `"rel"`.Convert RelName :employees to string:
def output(x) = relname_string(:employees, x)
//output> "employees"Convert RelName :employees to string using equivalent shorthand:
def output = relname_string[:employees]See Also
remainder
View sourceremainder[x, y]
remainder(x, y, r)
x % yRemainder from truncated division.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Number | Dividend. Must be grounded. |
y | Number | Divisor. Must be grounded. |
r | Number | Remainder. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | r |
|---|---|---|
Number | Same as x. | Same as x. |
SignedInteger, UnsignedInteger | SignedInteger, UnsignedInteger | SignedInteger[#n] or UnsignedInteger[#n], where n is the greater of the number of bits in the types of x or y. Signedness matches the type of x. |
FloatBinary, FixedDecimal | SignedInteger[#64] | Same as x. |
SignedInteger[#64] | FloatBinary, FixedDecimal | Same as y. |
Rational | SignedInteger[#64] | Rational[n], where n is the greater of the number of bits in the types of x and y. |
SignedInteger[#64] | Rational | Rational[n], where n is the greater of the number of bits in the types of x and y. |
Explanation
remainder is the remainder of x after truncated division of y.
That is, remainder[x, y] is equivalent to x - (y * trunc_divide[x, y]).
x % y is equivalent to remainder[x, y].
r has the same sign as x, and is smaller in magnitude than y.
The value for r is always exact.
remainder[x, y] is defined when either the types of x and y are the same, or
either operand is of type SignedInteger[#64] or FloatBinary[#64].
remainder is false (empty) when y = 0 for integer arguments.
Examples
Compute remainder of integer divided by integer using %.
def output = 8 % 3
//output> 2Compute remainder of integer divided by integer using remainder:
def output = remainder[-8, 3]
//output> -2Compute remainder of integer divided by negative integer using full expression:
def output(r) = remainder(8, -3, r)
//output> 2Compute remainder of rational divided by negative integer:
def output = remainder[rational[64, 8, 3], -2]
//output> 2/3Confirm that remainder is false (empty) when y is 0:
def output = empty(remainder[6, 0])
//output> () // truereverse_sort
View sourcereverse_sort[R]Reverse Sort
Like sort, except the ordering is reversed.
Example:
def sample = {'a'; 'b'; 'c'}
def output = reverse_sort[sample]
//output> (1, 'c')
// (2, 'b')
// (3, 'a')def sample = {(:g, 'a'); (:g, 'b'); (:g, 'c'); (:h, 'd'); (:h, 'e'); (:h, 'f')}
def output = x: reverse_sort[sample[x]]
//output> (:g, 1, 'c')
// (:g, 2, 'b')
// (:g, 3, 'a')
// (:h, 1, 'f')
// (:h, 2, 'e')
// (:h, 3, 'd')right_override
View sourceright_override[R, S]
R ++> SRight override is identical to left override, except the arguments are swapped.
R ++> S contains all of S, plus all the tuples in R whose key is not in S.
There are two equivalent ways to think about R ++> S:
(1) R is providing default values for keys that are missing in S.
(2) The entries in S are overriding the entries in R.
A few examples to illustrate the difference with left-override:
| Example | Value |
|---|---|
2 ++> 3 | 3 |
(1,2) ++> (1,3) | (1,3) |
(3,4) ++> (1,2); (3,5) | (1,2); (3,5) |
(3,"abc") ++> (1,2); (3,5) | (1,2); (3,5) |
(1,2); (3,5) ++> (3,4); (6,7) | (1,2); (3,4); (6,7) |
round
View sourceround[mode, x]
round(mode, x, r)Round x to an integer according to the given rounding mode. The rounded number is of the same data type as x.
Parameters
| Parameter | Type | Description |
|---|---|---|
mode | RelName | Mode for rounding. Must be grounded. |
x | Number | Number to be rounded. Must be grounded. |
r | Number | Result of rounding x. Same type as x. |
Available Modes
mode | Description |
|---|---|
:ROUND_UP | Round up to the nearest integer. |
:ROUND_DOWN | Round down to the nearest integer. |
:ROUND_NEAREST | Round to the nearest integer, with ties (fractional values of 0.5) being rounded to the nearest even integer. |
:ROUND_NEAREST_TIES_AWAY | Round to the nearest integer, with ties rounded away from zero. |
:ROUND_NEAREST_TIES_UP | Round to the nearest integer, with ties rounded toward positive infinity. |
:ROUND_TO_ZERO | Round toward zero to the nearest integer. |
Examples
Round nearest float:
def output = round[:ROUND_NEAREST, -8.555]
//output> 9.0Round up rational:
def output = round[:ROUND_UP, rational[64, 8, 3]]
//output> 3/1Round down float using full expression:
def output(r) = round(:ROUND_DOWN, 8.4, r)
//output> 8.0Round nearest float, showing ties away and ties up:
def output:away = round[:ROUND_NEAREST_TIES_AWAY, -8.5]
def output:up = round[:ROUND_NEAREST_TIES_UP, -8.5]
//output> (:away, -9.0)
// (:up, -8.0)Round to 0:
def output = round[:ROUND_TO_ZERO, -8.5]
//output> -8.0See Also
floor, floor_to_int, ceil, trunc, and trunc_to_int.
round
View sourceround[x]
round(x, r)Round x to the nearest integer. The rounded number is of the same data type as x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Number | Number to be rounded. Must be grounded. |
r | Number | Result of rounding x. Same type as x. |
Explanation
round[x] rounds to the nearest integer, with ties rounded to the nearest even integer.
It is equivalent to round[:ROUND_NEAREST, x].
For details see the docstring for round(mode, x, r).
Example
Rounding a floating-point number:
def output = round[9.7]
//output> 10.0Rounding a fractional:
def output = round[rational[64, 7, 3]]
//output> 2/1sample_standard_deviation
View sourcesample_standard_deviation[R]
sample_stddev[R]Sample standard deviation of (the last argument of) the relation R.
sample_stddev
View source
see: sample_standard_deviation
sample_zscore_normalization
View sourcesample_zscore_normalization[R]Z-score normalization (sample) of (the last argument of) the relation R.
Often simply referred to as ‘standardization’.
Second
View sourceSecond[n]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Second constructor, ^Second, instead.
Create a period of n seconds.
second
View sourcesecond[R]Projection to the second argument of R.
second supports heterogeneous relations, both in arity and types.
Examples:
def output = second[(1, 2, 3); (4, 5)]
//output> 2
// 5
def output = second[(1, 2); (3, "abc")]
//output> 2
// "abc"SignedInt
View sourceSignedInt(nbits, x)DEPRECATED
This relation is deprecated and should be avoided. It will be removed soon.
Please use SignedInteger instead. Note that SignedInteger takes a specialized integer
for nbits.
Holds if x is an nbits signed integer.
Examples:
Integrity constraint that tests whether x is an 8-bit signed integer:
def R = int[8, 5]
ic signed_type_check(x in R) {
SignedInt(8, x)
}SignedInteger
View sourceSignedInteger(#nbits, x)Holds if x is an nbits signed integer, where nbits is a specialized integer.
SignedInteger is a binary relation.
SignedInteger[#64] is a unary relation.
Examples:
Integrity constraint that tests whether x is an 8-bit signed integer:
def R = int[8, 5]
ic signed_type_check(x in R) {
SignedInteger[#8](x)
}Check whether x is any signed integer:
def x = int[16, 5]
def output = SignedInteger[_](x)SignedRational
View sourceSignedRational(#nbits, x)Holds if x is an nbits rational.
Parameters
| Parameter | Type | Description |
|---|---|---|
#nbits | #(Int) | A specialized integer (must be a valid bit size). |
x | Rational | A rational value. |
Examples
Query that checks that x is of type SignedRational with a bit size of nbits, a numerator of -5, and a denominator of -7:
def my_rational = rational[16, -5, -7]
def output(x) = my_rational(x) and SignedRational(#16, x)
//output> 5/7See Also
sin
View sourcesin[x]
sin(x, s)Sine of x, where x is an angle given in radians.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | SignedInteger[#64], FloatBinary[#64] | Angle in radians. Must be grounded. |
s | FloatBinary[#64] | Sine of x. |
Currently, only 64-bit float and integer values for x are supported.
Examples
Calculate the sine of π/2::
def output = sin[pi_float64/2]
//output> 1Calculate the sine of 5π/6:
def output = sin[5 * pi_float64/6]
//output> 0.49999999999999994See Also
asin, sinh, asinh, cos, acos, cosh, acosh, tan, atan, tanh, and atanh.
sinh
View sourcesinh[x]
sinh(x, sh)Hyperbolic sine. sh is the hyperbolic sine of x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Hyperbolic angle. Must be grounded. |
sh | FloatBinary[#64] | Hyberbolic sine of x. |
Explanation
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the hyperbolic sine of 7:
def output = sinh[7]
//output> 548.3161232732465Calculate the hyperbolic sine of -1 using full expression:
def output(x) = sinh(-1, x)
//output> -1.1752011936438014Confirm that 548.3161232732465 is the hyperbolic sine of 7:
def output = sinh(7, 548.3161232732465)
//output> () // trueSee Also
sort
View sourcesort(R, index, x...)Enumerate the tuples in a relation.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Relation to be enumerated. Must be grounded. |
index | Int | The new enumeration index starting at 1. |
x... | Tuples | A tuple in R associated with the new index index. |
Explanation
sort is an alias for enumerate.
The purpose of sort is to generate a global index across all tuples in R.
It should not be used to sort tuples by value, as the sorting order across data types and tuple lengths is not well defined.
The enumeration is deterministic meaning enumerating the same tuples will always produce the same result.
For more information on how tuples are indexed, see the docstring for enumerate.
See Also
soundex
View sourcesoundex[string_value]soundex returns a four-letter encoding the phonetic representation of string_value.
soundex lets you compare words and sentences based on how they sound in English.
string_value could be any arbitrary long string, but only the first few syllables are
considered for the result.
Examples:
def output = soundex["Smith"]
//output> s530
def output = soundex["Smythe"]
//output> s530
def output = soundex["Christina"]
//output> c623
def output = soundex["Cristine"]
//output> c623Here is a simple illustration. Consider the following:
def my_favorite_bands = { "Metallica"; "Iron Maiden"; "Wolfheart"; "Insomium" }
def do_I_like = "Mee ta li ka"
def output = exists({ y : soundex[my_favorite_bands][y] and equal(y, soundex[do_I_like]) })The script above evaluates to true since "Mee ta li ka" and
"Metallica" have the same soundex code.
spread
View sourcespread[mode, R, value]
spread(mode, R, value, x..., spread)Spread value to the tuples in relation R, either evenly or proportionally to their
weight, which is the last element in each tuple.
Parameter
| Parameter | Type | Description |
|---|---|---|
mode | RelName | :even or :ratio. |
R | Relation | Source relation. Must be grounded. |
value | Int, FixedDecimal | Integer or decimal to be divided among tuples as spread. Must be grounded. |
x... | Tuple | A tuple in R. |
spread | Float | Spread associated with x.... |
Explanation
spread takes a relation R(x...) and produces a relation with the tuples (x..., spread) where the last element of each tuple (spread)
is a spread of value distributed among tuples.
When mode is :even, spread is value divided evenly among tuples.
When mode is :ratio, spread is value divided proportionally to a tuple’s
weight — the last element in each tuple.
spread can be either an integer or a decimal depending on the type of value.
That is, if you use a decimal for value, spread behaves like FixedDecimal_spread.
If you use an integer for value, spread behaves like either int_spread_by_even or int_spread_by_ratio, depending on mode.
spread is empty if value is negative.
Examples
Spread using a value that is a decimal.
Note that spread is a decimal with the same number of places as value, just as would be the case with FixedDecimal_spread:
def R = {("Atlanta", 50);
("Seattle", 80);
("San Francisco", 10)}
def output = spread[:even, R, decimal[#64, #3, 31.0] ]
//output> Atlanta, 50, 10.334
// San Francisco, 10, 10.333
// Seattle, 80, 10.333Spread using a value that is an integer.
Note that spread is an integer:
def R = {("Atlanta", 50);
("Seattle", 80);
("San Francisco", 10)}
def output = spread[:even, R, 31]
//output> Atlanta, 50, 11
// San Francisco, 10, 10
// Seattle, 80, 10Spread using full expression, using a decimal as spread:
def R = {("Miles Davis", 65); ("Jimmy Smith", 76); ("Ornette Coleman", 85)}
def output = spread[:ratio, R, decimal[#64, #3, 88.55]]
//output> Jimmy Smith, 29.778
// Miles Davis, 25.468
// Ornette Coleman, 33.304See Also
int_spread_by_ratio, int_spread_by_even, and FixedDecimal_spread.
squared
View sourcesquared[R]Square of a relation: the value of each last element is squared.
Examples:
def example = {(1, 2); (3, 4)}
equal(square[example], {(1, 4); (3, 16)}squared_deviation
View sourcesquared_deviation[R]Squared deviation: squared deviation from the mean of (the last argument of) the relation R.
starts_with
View sourcestarts_with(s, prefix)True if and only if the specified string s begins with the given prefix prefix.
Examples:
starts_with("abc", "ab") // true
starts_with("abc", "bc") // false
starts_with("abc", "abcd") // false
starts_with("abc", "Ab") // falsestring
View sourcestring[x]Convert ints, floats, dates, periods, to strings:
Examples:
string[1] = "1"
string[3.4] = "3.4"
string[unix_epoch] = "1970-01-01T00:00:00"
string[^Hour[1]] = "1 hour"
string["a"] = "a"
string[:a] = "a"String
View sourceString(x)Holds if x is a String. Strings are specified by double quotes, for example, "abc".
Examples:
Integrity constraint that tests whether x is of type String:
def R = "foo"
ic string_type_check(x in R) {
String(x)
}Schema defined in a relation using String:
def myrelation(x in String, y in Int) {
x = "abc" and y = 123
}
def output = myrelation
//output> (abc, 123)string_join
View sourcestring_join[separator, R]
string_join(separator, R, new_string)Concatenate the string values in the binary relation R into one string and insert the string, separator, between two adjacent strings.
Parameters
| Parameter | Type | Description |
|---|---|---|
separator | Char or String | Character or String used to separate adjacent strings. Must be grounded. |
R | Relation | A binary relation containing tuples of the form (Int, String). Must be grounded. |
new_string | String | Resulting string containing all the strings in R separated by separator. |
Explanation
The binary relation R can only contain tuples (index, text) with the signature (Int, String).
The purpose of the two elements are:
- The integer
indexrepresents the order of the strings to be joined, and serves as the sort key for concatenation. - The string
textrepresents the Strings that will be concatenated together.
If R is empty, the expression string_join[separator, R] is false and no new string is created.
Examples
Concatenate using ", " as separator:
def output = string_join[", ", {(1, "a"); (2, "b"); (3, "c")}]
//output> "a,b,c"Concatenate using the character ' ' as separator:
def output = string_join[' ', {(1, "hello"); (2, "world")}]
//output> "hello world"Using string_join and sort to order a set of Strings alphabetically and join them together with "->" as separator:
def output = string_join["->", sort[{"x"; "y"; "z"}]]
//output> "x->y->z"See Also
string_length, string_replace, string_replace_multiple, string_split, and string_trim.
string_length
View sourcestring_length[string]DEPRECATED
This function is deprecated. Use num_chars[string] or num_bytes[string],
depending on your need.
Example:
string_length["foo"] = 3string_replace
View sourcestring_replace[string, old_str, new_str]Replace a string or character in string with the specific string or character.
Examples:
string_replace["One Two Three", "One", "1"] = "1 Two Three"
string_replace["Rel", 'R', 'r'] = "rel"string_replace_multiple
View sourcestring_replace_multiple[input, R]Replaces all occurrences of old string in input with the corresponding new string, for each tuple (old, new) in relation R.
Examples:
string_replace_multiple["One Two Three", {("One", "1"); ("Two", "2")}]
// "1 2 Three"string_replace_multiple["One Two Three", {('O', 'o'); ('T', 't')}]
// "one two three"The behavior is undefined if new generates more occurrences of old.
string_split
View sourcestring_split[delimiter, text]Split the string text into the substrings delimited by delimiter (and the
start/end of text).
The expression string_split[delimiter, string] evaluates to a relation of the format
(index, sub_string) where index is the substring’s position of type Int and
sub_string is the matched substring of type String.
delimiter can be a String or a Char.
Example:
string_split['@', "user@email.com"] = {(1, "user"); (2, "email.com")}
string_split[" ", "a b c"] = {(1, "a"); (2, "b"); (3, ""); (4, "c")}string_trim
View sourcestring_trim[s]To remove leading and tailing white spaces in given string s.
Example:
string_trim[" Good Day!!! "] = "Good Day!!!"subset
View sourcesubset(R, S)
R ⊆ SR is a subset of S if all facts in R are also in S.
Subset is the relational variant of implication, but note that there is a subtle difference for arity-overloaded relations due to usage of varargs.
-
forall(x, y: R(x, y) implies S(x, y))is true if the implication is true for all binary facts ofR. IfRalso contains facts of a different arity, then the implication remains true, even whenR ⊈ S. -
subset(R, S), defined asforall(xs... where R(xs...) : S(xs...)), is true only if there exists no fact inR, of any arity, that is not also inS.
substring
View sourcesubstring[mystring, i, j]
substring(mystring, i, j, substring)Find a substring (substring) within mystring that starts at index i and ends at index j.
Parameters
| Parameter | Type | Description |
|---|---|---|
mystring | String | Source text. Must be grounded. |
i | SignedInteger, UnsignedInteger | The position where substring begins. Must be grounded. |
j | SignedInteger, UnsignedInteger | The position where substring ends. Must be grounded. |
substring | String | A string that begins at the i-th character and ends at the j-th character. |
Explanation
The index of a string’s first character is 1.
When i and j are out of bounds on the same end, or i > j, the empty string is returned.
If i < 1 the substring will start with the first character in mystring.
If j > length[mystring] the substring ends with the last character in mystring.
Examples
Get the two-character string beginning with position 2:
def output = substring["abcd", 2, 3]
//output> bcGet a two-character string beginning with position 2 using full expression:
def output(x) = substring("中文例子", 2, 3, x)
//output> 文例Substring that returns empty because i > j:
def output = substring["abcd", 3, 2]
//output> ""Substring that returns empty because i and j are out of bounds:
def output = substring["abcd", 5, 7]
//output> ""Get the substring containing the first three characters with i out of bounds:
def output = substring["abcd", -2, 3]
//output> abcGet the substring containing the characters starting at index 2 and with j out of bounds:
def output = substring["abcd", 2, 7]
//output> bcdSee Also
substring_bytes, starts_with, ends_with, and string_replace.
substring_bytes
View sourcesubstring_bytes[string, index1, index2]Extracts substring of a string between the byte range [index1:index2] (both inclusive).
The byte index starts with 1.
When index1 and index2 are out of bounds on the same end, or index2 < index1,
the empty string is returned.
Otherwise, both indices are clamped in range.
Use substring to extract substrings by character indices.
Examples:
substring_bytes["abcd", 2, 3] = "bc"
substring_bytes["abcd", 3, 2] = ""
substring_bytes["word", 0, 10] = "word"Note that non-ASCII characters require usually more than one byte per character:
substring_bytes["中文例子", 1, 6] = """中文"""subtract
View sourcesubtract[x, y]
subtract(x, y, d)
x - ySubtraction of one number from another. Subtraction of a date, datetimes, and periods.
Parameters
Numeric Data
| Parameter | Type | Description |
|---|---|---|
x | Number | Subtrahend. |
y | Number | Minuend. |
d | Number | Difference x - y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | d |
|---|---|---|
Number | Same as x | Same as x |
SignedInteger[#64] | SignedInteger[#128], FloatBinary[#64], FixedDecimal, Rational | Same as y |
SignedInteger[#128], FloatBinary[#64], FixedDecimal, Rational | SignedInteger[#64] | Same as x |
Two of the three arguments need to be grounded. Valid grounding combinations are as follows:
xandy.xandd.yandd.
Time Data
| Parameter | Type | Description |
|---|---|---|
x | Date, DateTime, date period, time period | Minuend. |
y | Date, DateTime, date period, time period | Subtrahend. |
d | Date, DateTime, date period, time period | Difference x - y. |
The following combinations work:
x | y | d |
|---|---|---|
| date period, time period | Same date period, time period as x | Same Date period, time period as x |
DateTime | date period, time period | DateTime |
DateTime | DateTime | Time period in Millisecond |
Date | date period | Date |
Date | Date | date period in Day |
Two of the three arguments need to be grounded. Valid grounding combinations are as follows:
xandy.xandd.yandd.
Explanation
subtract maps the pair x, y to d, which is the difference x - y.
In procedural languages, usually x and y are given.
In Rel — a declarative language — subtraction can be thought of as a mapping where x and y are the keys and d is the value, which is functionally dependent on x and y.
However, with subtraction — subtract(x, y, d) — it is sufficient to know any two of the three arguments.
The third argument can always be inferred.
Usually x and y are given, but knowing x and d is enough to infer y.
Examples
Subtract two numerals using -:
def output = 8 - 5
//output> 3Subtract a float from an integer using subtract:
def output = subtract[7, 5.25]
//output> 1.75Subtract two floats using full expression:
def output(x) = subtract(8.5, 5.25, x)
//output> 3.25Subtract a rational from an integer:
def output = x - rational[16, 2, 3]
//output> 4/3Calculate integer subtracted by providing x and d:
def output(y) = subtract(2899, y, 2865)
//output> 34Subtraction of Time
Subtract a time period and a date period from a timestamp:
def output:yesterday = datetime_now - ^Day[1]
def output:last_hour = datetime_now - ^Hour[1]
//output> (:last_hour, 2022-11-17T13:01:52.537Z)
// (:yesterday, 2022-11-16T14:01:52.537Z)Subtract a timestamp from a timestamp and get the difference in milliseconds. Note that the second date is defined in a different time zone and the time difference is 58 hours, or 136800000 milliseconds:
def output = 2021-10-12T01:00:00+00:00 - 2021-10-10T01:00:00+10:00
//output> 136800000Subtract weeks from a date:
def output = 2024-01-10 - ^Week[2]
//output> 2023-12-27Subtract two dates from each other and retrieve the number of days between them. Here, the date period is negative because the second date occurs later:
def output = 2023-12-30 - 2024-01-10
//output> -11Calculate date subtracted by providing date and resulting period:
def output(y) = subtract(2022-10-01, y, ^Day[10])
//output> 2022-09-21Subtract 2 seconds from 6 seconds:
def output = ^Second[6] - ^Second[2]
//output> 4See Also
suffix_join
View sourcesuffix_join[R, S]
R :> SThe suffix join (or restriction) of R to S consists of the tuples (x..., y...) in R where the suffix (y...) is in S.
That is, R :> S contains the tuples in R that have a suffix in S.
| Example | Normalized |
|---|---|
edge :> n | x, y: edge(x, y) and y = n |
parent :> female | x, y: parent(x, y) and female(y) |
account_balance :> positive | x, v: account_balance(x, v) and positive(v) |
brand_name :> "Tesla" | b, s: brand_name(b, s) and s = "Tesla" |
The restriction operator can also be used to select subsets of JSON-like relations:
-
json :> evenwherejsonis[ {"a": 1, "b": 2}, {"a": 3, "b": 4, "c": 6} ]has value[ {"b": 2}, {"b": 4, "c": 6} ] -
json :> (:b, even)wherejsonis[ {"a": 1, "b": 2}, {"a": 3, "b": 4, "c": 6} ]has value[ {"b": 2}, {"b": 4} ]
sum
View sourcesum[R]
sum(R, s)
Σ[R]
Σ(R, s)Sum of the last element of all tuples in a relation.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Source relation. Must be grounded. |
s | Number | The sum of the last element of R. |
Explanation
sum aggregates over all tuples in R whose last element is numeric.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
For example, if R contains key-value pairs, sum[R] calculates the sum of values for R.
Note that sum groups the tuples by the data type of the final numeric element.
Typically, sum is used when the last elements of each tuple have the same type.
If R is empty, sum[R] is false (empty).
To get 0 instead, use left override, as in sum[R] <++ 0.
Examples
Calculate the sum of integers:
def salary = {("John", 10) ; ("Mary", 20); ("Paul", 17) ; ("Peter", 15) }
def output = sum[salary]
//output> 62Calculate the sum of R for each data type:
def R = {(1, "1"); (2, 2); (3, 3.0); (4, 4)}
def output = sum[R]
//output> 3.0
6Calculate the sum of R using full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7)}
def output(s) = sum(R, s)
//output> 25.8Calculate the total salary by department using group-by:
def department = {"A"; "B"; "C" }
def member = {("A", "John"); ("B", "Mary"); ("A", "Paul"); ("C" , "Peter"); ("C", "Tran")}
def salary = {("John", 126) ; ("Mary", 90); ("Paul", 117); ("Peter", 115); ("Tran", 145)}
def output = d in department: sum[salary[p] for p in member[d]]
//output> "A", 243
// "B", 90
// "C", 260See Also
sum_int
View sourcesum_int[R]
sum_int(R, si)Sum over the last elements in the tuples of R, which must be integers.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | A grounded relation. The last element of every tuple must be an integer. |
si | SignedInteger[#64] | The integer sum of the last element of R. |
Explanation
sum_int sums over the last elements of every tuple in R.
Every last element must be an integer.
If this is not the case, invoking sum_int[R] will trigger an error.
Tuples in R can have different lengths, and only the last element in each tuple is used for the sum.
In contrast to sum, sum_int[R] evaluates to 0 if R is empty.
Examples
Find the integer sum of a relation:
def R = {("Oakland", 22); ("Fresno", 11); ("Palo Alto", 15); ("Eureka", 40)}
def output = sum_int[R]
//output> 88Evaluate the sum of a relation with various tuple lengths:
def salary = {("John", 10) ; ("Mary", "Smith", 20); }
def output = sum_int[salary]
//output> 30The sum over an empty relation is zero:
def output = sum_int[{}]
//output> 0See Also
tan
View sourcetan[x]
tan(x, t)Tangent. t is the tangent of x, where x is in radians.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Angle in radians. Must be grounded. |
t | FloatBinary[#64] | Tangent of x. |
Defined for non-infinite x.
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the tangent of π/4:
def output = tan[pi_float64/4]
//output> 0.9999999999999999Convert degrees to radians and calculate tangent using full expression:
def x = deg2rad[90]
def output(t) = tan(x, t)
//output> 16331239353195370.0Confirm that 0.9999999999999999 is the tangent of π/4:
def output = tan(pi_float64/4, 0.9999999999999999)
//output> () // trueSee Also
tanh
View sourcetanh[x]
tanh(x, th)Hyperbolic tangent. th is the hyperbolic tangent of x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FloatBinary[#64], SignedInteger[#64] | Hyperbolic angle. Must be grounded. |
th | FloatBinary[#64] | Hyberbolic tangent of x. |
Explanation
Only 64-bit float and 64-bit integer values for x are supported.
Examples
Calculate the hyperbolic tangent of 7:
def output = tanh[7]
//output> 0.9999983369439447Calculate the hyperbolic tangent of -1 using full expression:
def output(x) = tanh(-1, x)
//output> -0.7615941559557649Confirm that 0.9999983369439447 is the hyperbolic tangent of 7:
def output = tanh(7, 0.9999983369439447)
//output> () // trueSee Also
top
View sourcetop[k, R]
top(k, R, index, x...)Select the top k tuples of relation R according to the lexicographic order of R and add enumeration.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | Source relation. Must be grounded. |
k | Int | Number of tuples to enumerate from the top of R. Must be grounded. |
index | Int | The new enumaration index starting at 1. |
x... | Tuple | A tuple in R associated with the new index index. |
Explanation
top is enumerate restricted to the first k tuples of R.
top first puts the tuples of R in lexicographical order and then limits the result to the first k tuples.
For details on lexicographical ordering — particularly across data types — see enumerate.
Similar to enumerate, top takes a relation R(x...) and produces a relation with the tuples (index, x...),
where the first element of each tuple (index) is an integer index that enumerates the top k tuples
in the original relation R.
If k is bigger than the number of tuples in the relation R, then top[k, R] is equivalent to enumerate[R].
The relation R can contain tuples of various sizes.
top[k, R] supports group-bys in R but not in k.
For example, the following is supported:
def output[g] = top[k, R[g]]However, the following is not supported:
def output[g] = top[k[g], R]Examples
Apply top to a relation with arity-1 tuples:
def output = top[2, {'a'; 'b'; 'c'; 'd'}]
// output> (1, 'a')
// (2, 'b')Apply top to a relation with arity-2 tuples:
def R = {('a', 1); ('b', 2); ('c', 3); ('d', 4); ('e', 5)}
def output = top[3, R]
//output> 1, a, 1
// 2, b, 2
// 3, c, 3See Also
bottom, enumerate, sort, and reverse_sort.
total
View sourcetotal(D, F)Given a domain D and a relation F, check that there is a value in F for every element of the domain D. The arity of F must be the arity of D + 1.
transpose
View sourcetranspose[R]Transpose a binary relation (swap the two arguments).
Example:
def output = transpose[{(1, 2); (3, 4)}]
//output> (2, 1)
// (4, 3)trunc
View sourcetrunc[x]
trunc(x, t)Round toward zero to the nearest integer.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Number | Number to be rounded toward zero. Must be grounded. |
t | Int | Truncated x. |
Return type is the same as x.
Explanation
Rounds toward zero for both positive and negative x.
Examples
Truncate float:
def output = trunc[3.9]
//output> 3.0Truncate negative float using full expression:
def output(t) = trunc(-4.9, t)
//output> -4.0Truncate rational:
def output = trunc[rational[64, 27, 5]]
//output> 5/1See Also
floor, floor_to_int, ceil, trunc_to_int, and round.
trunc_divide
View sourcetrunc_divide[x, y]
trunc_divide(x, y, q)
x ÷ yDivision of two numbers, rounding the result to the nearest integer toward zero.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Number | Numerator. Must be grounded. |
y | Number | Denominator. Must be grounded. |
q | Number | Truncated quotient x / y. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | q |
|---|---|---|
SignedInteger[#64] | SignedInteger[#64] | SignedIneger[#64] |
SignedInteger[#64] | FloatBinary[#64] | FloatBinary[#64] |
FloatBinary[#64] | SignedInteger[#64], FloatBinary[#64] | FloatBinary[#64] |
Rational | SignedInteger[#64] | SignedInteger[#64] |
FixedDecimal | SignedInteger[#64] | Same as x |
Explanation
trunc_divide maps the pair x, y to q, which is the truncated quotient x/y.
Similar to divide and in contrast to add and subtract, x and y need to be grounded and specified by the user.
Specifying only x and q or only y and q is not sufficient, because the system can’t compute the inverse.
trunc_divide is false (empty) when y = 0 for integer arguments.
Examples
Use truncated division to divide an integer by another integer using ÷:
def output = 5 ÷ 2
//output> 2Use truncated division to divide an integer by another integer using trunc_divide:
def output = trunc_divide[5, 2]
//output> 2Use truncated division to divide a negative integer by a positive integer:
def output = trunc_divide[-5, 2]
//output> -2Use truncated division to divide a decimal by an integer using full expression:
def output(x) = trunc_divide(5.1, 2, x)
//output> 2.0Use truncated division to divide a rational by an integer using full expression:
def output(t) = trunc_divide(rational[64, 26, 3], 2, t)
//output> 4trunc_to_int
View sourcetrunc_to_int[x]
trunc_to_int(x, t)Convert float to integer, truncating.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | Float | Number to be rounded down. Must be grounded. |
t | Int | Truncated x, integer. |
Explanation
Rounding goes toward zero for both postivie and negative x.
Examples
Convert float to integer, truncating:
def output = trunc_to_int[3.1]
//output> 3Convert negative float to integer, truncating, using full expression. Note that rounding goes toward zero.
def output = trunc_to_int[-3.1]
//output> -3Confirm that trunc_to_int returns false (empty) when x is an integer:
def output = trunc_to_int[3]
//output> // falseSee Also
floor, floor_to_int, ceil, trunc, and round.
uint
View sourceuint[n, v]The n-bit unsigned integer value from the positive integer value v.
n must be among 8, 16, 32, 64, and 128 and v is encodable with n-bits.
Examples:
uint[8, 42] = 42
empty(uint[128, -300])
empty(uint[8, 300])uint128_hash_value_convert
View sourceuint128_hash_value_convert[v]Convert a provided UInt128 value v to the HashValue type.
This is an internal-facing function, used for the implementation of hashing.
uint128_uint64_truncate
View sourceuint128_uint64_truncate[v]Truncates v of type UInt128 to a UInt64 number.
Truncates the high order bits in v and converts the remaining bits to UInt64.
Truncate always succeeds. For values larger than 2^64, consists of only the lower bits.
Examples:
uint128_uint64_truncate[uint128[1]] = 1
uint128_uint64_truncate[uint128[2] ^ 64 + uint128[1]] = 1unpack
View sourceunpack(v, x₁, ..., xₙ)Unpacks a packed structure v into its arguments x₁, ..., xₙ.
unpack cannot be used with point-free syntax.
Direct usage of unpack should be avoided, as it serves primarily as a low-level
interface for value types.
UnsignedInt
View sourceUnsignedInt(nbits, x)DEPRECATED
This relation is deprecated and should be avoided. It will be removed soon.
Please use UnsignedInteger instead. Note that UnsignedInteger takes a specialized integer
for nbits.
Holds if x is an unsigned integer of the bit length nbits.
Example:
Integrity constraint that tests whether x is a 32-bit unsigned integer:
def my_unsigned_int = uint[32, 1234]
ic my_unsigned_ic(x) {
my_unsigned_int(x) implies UnsignedInt(32, x)
}UnsignedInteger
View sourceUnsignedInteger(#nbits, x)Holds if x is an nbits unsigned integer, where nbits is a specialized integer.
UnsignedInteger is a binary relation.
UnsignedInteger[#64] is a unary relation.
Examples:
Integrity constraint that tests whether x is an 8-bit unsigned integer:
def R = uint[8, 5]
ic unsigned_type_check(x in R) {
UnsignedInteger[#8](x)
}Check whether x is any unsigned integer:
def x = uint[16, 5]
def output = UnsignedInteger[_](x)uppercase
View sourceuppercase[string_or_char]A string where all the characters are converted to uppercase. If a character is already uppercase or has no uppercase version, it remains unchanged.
Example:
def output = uppercase["aB1c"]
//output> "AB1C"
def output = uppercase['â']
//output> 'Â'uppercase does not take a locale option and does not handle local-specific case mapping
rules.
uuid_string
View sourceuuid_string[v]Convert a UInt128, Hash or rel:base:UUID value to the standard UUID string format.
Example:
uuid_string[0x22b4a8a1e5484eeb927060426d66a48e] = "22b4a8a1-e548-4eeb-9270-60426d66a48e"Week
View sourceWeek[n]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Week constructor, ^Week, instead.
Create a period of n weeks.
weighted_mean
View sourceweighted_mean[R, W]
weighted_mean(R, W, wm)The weighted mean of the last element of each tuple in a relation R with weights defined by W.
Parameters
| Parameter | Type | Description |
|---|---|---|
R | Relation | A relation whose last elements contain numeric data types and whose first elements match W. Must be grounded. |
W | Relation | Weight for weighted mean. A relation whose last elements contain numeric data types and whose first elements match R. Must be grounded. |
wm | Number | The weighted mean of R. |
Explanation
The weighted mean of a relation R is the sum of the last elements in each tuple of R,
weighted by the last element of the corresponding tuple in W.
A tuple in R corresponds to a tuple in W if the first elements of the tuples match
— that is, they have the same key.
weighted_mean aggregates over all tuples in R whose last element is numeric.
Tuples in R can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that weighted_mean groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, weighted_mean is used when the last elements of each tuple have the same type.
Examples
Calculate weighted mean of a relation:
def inputs = {(:class_participation , 90); (:assignment_1, 85); (:assignment_2, 81); (:midterm, 76); (:final, 83)}
def weights = {(:class_participation, 10); (:assignment_1, 20); (:assignment_2, 20); (:midterm, 20); (:final, 30)}
def output = weighted_mean[inputs, weights]
//output> 82.3Calculate weighted mean when the arities of R and W are different:
def R = {(1, "cp", 90); (2, "a1", 85); (3, "a2", 81); (4, "mt", 76); (5, "f", 83)}
def W = {(1, 10); (2, 20); (3, 20); (4, 20); (5, 30)}
def output = weighted_mean[R, (k1, k2, v: W(k1, v) and Any(k2))]
//output> 82.3Calculate weighted mean when the arities of R and W are different:
def R = {(1, 'a', 100, 90); (2, 'a', 200, 85); (3, 'b', 300, 81); (4, 'c', 400, 76); (5, 'b', 500, 83)}
def W = {(1, 'a', 10); (2, 'a', 20); (3, 'b', 20); (4, 'c', 20); (5, 'b', 30)}
def output = weighted_mean[R, (n, c: _, W[n, c])]
//output> 82.3See Also
geometric_mean, harmonic_mean, mean, mode, max, min, sum, and product.
xor
View sourceF xor G
F ⇎ G
F ⊻ GExclusive OR, for boolean (arity 0, true or false) arguments F and G.
Year
View sourceYear[n]DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Year constructor, ^Year, instead.
Create a period of n years.
zip
View sourcezip[R, S]Pair-wise combine two n-ary tuples into a relation of n pairs.
Example:
def foods = {(:hamburger, :chicken, :hot_dog, :fries, :macaroni, :pizza, :salad, :milk, :ice_cream)}
def cost = { (2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59) }
def output = zip[foods, cost]
//output> (:chicken, 2.89)
// (:fries, 1.89)
// (:hamburger, 2.49)
// (:hot_dog, 1.5)
// (:ice_cream, 1.59)
// (:macaroni, 2.09)
// (:milk, 0.89)
// (:pizza, 1.99)
// (:salad, 2.49)Module: rel:base
View sourceFilePos
View sourceFilePos(x)
^FilePos(y, x)The data type FilePos.
The type relation Filepos checks whether x is of type FilePos.
The constructor ^FilePos maps an integer, y, to its corresponding FilePos value, x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | FilePos | FilePos variable. |
y | Integer | The value of the FilePos data type. |
Explanation
The data type FilePos is defined via a value type declaration, and provides the semantic meaning of a file position to its integer value y.
Filepos values are used to identify CSV rows when CSV data is loaded into the RKGS.
For more information on CSV loading, see the CSV data and import guides in the RAI documentation (opens in a new tab).
Examples
A FilePos value can be created with the constructor ^FilePos:
def output = ^FilePos[10]The constructor can also be used to extract the integer value “back out” of the value type.
def fp = ^FilePos[4]
def output(i) = exists(x: ^FilePos(i, x) and fp(x))The type relation FilePos can be used to check that a value is of this data type.
def data = { 1; ^FilePos[2]}
def output(x) { data(x) and FilePos(x)}The relation load_csv that loads CSV data into the system automatically generates FilePos values that identify the row of the CSV file.
def config:data = """
item, category
laptop, computer
monitor, peripheral
"""
//FilePos automatically generated
def csv = load_csv[config]
def output = csv
def csv_ic {
subset(csv, (RelName, FilePos, String))
}FixedDecimal
View sourceFixedDecimal(v)
^FixedDecimal[bits, precision]
^FixedDecimal(bits, precision, v)Data type of fixed precision numbers with the type relation FixedDecimal and the constructor ^FixedDecimal.
bits is the width of the integer type used to back the fixed decimal,
precision is the number of decimal places, and v is the integer
representation of the fixed decimal. v must fit into a bits-wide
integer.
The integer representation of a fixed decimal is that number multiplied
by 10 ^ precision. For example, to represent the number 2.3 with a
precision of 3, we would use 2.3 * (10 ^ 3) = 2300.
Other constructors like decimal and parse_decimal are a simpler
way to construct a FixedDecimal.
Examples
Construct a 32-bit FixedDecimal with a precision of 3 decimal places equivalent to 5.5.
def output = rel:base:^FixedDecimal[#32, #3, 5500]
//output> (:rel, :base, :FixedDecimal, #32, #3, 5500)Attempt to construct a 8-bit FixedDecimal with a precision of 2 decimal places representing 200.
def output = rel:base:^FixedDecimal[#8, #2, 20000]
//output> {} // produces empty output as 20000 is too large to fit into an 8-bit integer.Check values are fixed decimals:
with rel:base use ^FixedDecimal, FixedDecimal
def output = FixedDecimal(^FixedDecimal[#8, #1, 1])
//output> () // true
def output = FixedDecimal(^FixedDecimal[#32, #3, 5500])
//output> () // true
def output = FixedDecimal(decimal[#32, #3, 5.5])
//output> () // true
def output = FixedDecimal(parse_decimal[#32, #3, "5.5"])
//output> () // true
def output = FixedDecimal(5.5)
//output> {} // false, the provided value is a FloatSee Also
decimal and parse_decimal.
UUID
View sourceUUID(x)
^UUID(y, x)The data type UUID.
The type relation UUID(x) checks whether x is of type UUID.
The constructor ^UUID(y, x) maps a UInt128, y, to its corresponding UUID value, x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | UUID | UUID variable. |
y | UInt128 | The value of the UUID data type. |
Explanation
UUID is an efficient representation of UUID values (compared to treating UUIDs as
strings). Compared to a plain UInt128, it provides tools with the information to format
and treat the value as a UUID.
To use rel:base:UUID or rel:base:^UUID the full name must be used or abbreviated
as with rel:base use UUID, ^UUID. The relations UUID and ^UUID are not
available as an alias without rel:base.
Examples
A UUID value can be created with the constructor ^UUID with a UInt128 argument:
with rel:base use ^UUID
def output = ^UUID[0x8f9924a8494741e80c464d9df14fe1d0]
//output> (:rel, :base, :UUID, 190874768316354382993454873408336552400)To create a UUID from a string, use uuid_from_string:
with rel:base use uuid_from_string
def output = uuid_from_string["184f8380-ba48-494a-9d77-2f410c9aef28"]
//output> (:rel, :base, :UUID, 32314330545176713121947364484890423080)To format UUID as a standard UUID string, use string.
with rel:base use uuid_from_string
def example = uuid_from_string["184f8380-ba48-494a-9d77-2f410c9aef28"]
def output = string[example]
//output> "184f8380-ba48-494a-9d77-2f410c9aef28"The constructor can be used to extract the integer value “back out” of the value type.
with rel:base use uuid_from_string, ^UUID
def example = uuid_from_string["184f8380-ba48-494a-9d77-2f410c9aef28"]
def output(i) = exists(x: ^UUID(i, x) and example(x))
//output> 32314330545176713121947364484890423080The type relation UUID can be used to check that a value is of this data type.
with rel:base use uuid_from_string, UUID
def example = uuid_from_string["184f8380-ba48-494a-9d77-2f410c9aef28"]
def data = 1; example
def output(x) = data(x) and UUID(x)
//output> (:rel, :base, :UUID, 32314330545176713121947364484890423080)The UUID value type is used by load_csv for columns with schema "uuid":
def config:data = """
A,B
1,b3b8a827-685f-4239-b0b3-afc41dfdc75c
2,6c8440c6-c441-4c75-9d36-1deb97f734ea
3,72327575-620b-4540-b13b-bdfe8e3ea24c
"""
def config:schema:A = "int"
def config:schema:B = "uuid"
def output = load_csv[config]
// output>
// (:A, 2, 1)
// (:A, 3, 2)
// (:A, 4, 3)
// (:B, 2, (:rel, :base, :UUID, 238890604434483702785039736746549299036))
// (:B, 3, (:rel, :base, :UUID, 144243320552226326224531778065386648810))
// (:B, 4, (:rel, :base, :UUID, 151793988704368948489985156409689285196))JSON export formats UUID values automatically to the standard string representation.
uuid_from_string
View sourceuuid_from_string(s in String, x in UUID)Parse a UUID string (in the standard 8-4-4-4-12 format) to a UUID value.
Example:
with rel:base use uuid_from_string
def output = uuid_from_string["22b4a8a1-e548-4eeb-9270-60426d66a48e"]
//output> (:rel, :base, :UUID, 46131785562730469527277340045557015694)SHA1
View sourceSHA1(x)
^SHA1(a in UInt128, b in UInt32, x)The data type SHA1.
The type relation SHA1(x) checks whether x is of type SHA1.
The constructor ^SHA1(a, b, x) maps a UInt128 a and a UInt32 b to the SHA1 value x.
Parameters
| Parameter | Type | Description |
|---|---|---|
x | SHA1 | SHA1 variable. |
a | UInt128 | The first 128 bits of the 160 bits SHA-1 value. |
b | UInt32 | The last 32 bits of the 160 bits SHA-1 value. |
Explanation
SHA1 is an efficient representation of SHA-1 values (compared to treating SHA-1 as
strings). The value type provides tools with the information to format and treat the
value as a SHA-1 hash.
To use rel:base:SHA1 or rel:base:^SHA1 the full name must be used or abbreviated
as with rel:base use SHA1, ^SHA1. The relations SHA1 and ^SHA1 are not
available as an alias without rel:base.
Examples
A SHA1 value can be created with the constructor, though it requires passing in the
two separate parameters. SHA-1 uses 160 bits and Rel does not have 160-bit integer type.
with rel:base use ^SHA1
def output = ^SHA1[0x0d7d4a744fd92effd1ed88e48ac8231e, 0x7f7e9e6c]
//output> (:rel, :base, :SHA1, 17930511166010156306237819770844488478, 2139004524)To format SHA1 as a standard hexadecimal string, use string.
with rel:base use ^SHA1
def example = ^SHA1[0x0d7d4a744fd92effd1ed88e48ac8231e, 0x7f7e9e6c]
def output = string[example]
//output> "0d7d4a744fd92effd1ed88e48ac8231e7f7e9e6c"The type relation SHA1 can be used to check that a value is of this data type.
with rel:base use SHA1, sha1_from_string
def example = sha1_from_string["0d7d4a744fd92effd1ed88e48ac8231e7f7e9e6c"]
def data = 1; example
def output(x) = data(x) and SHA1(x)
//output> (:rel, :base, :SHA1, 17930511166010156306237819770844488478, 2139004524)The SHA1 value type is used by load_csv for columns with schema "sha-1":
def config:data = """
A,B
1,0d7d4a744fd92effd1ed88e48ac8231e7f7e9e6c
2,10bb3e970ba01ec67439f1764da9ff43b5a7edd5
3,187ca6345d5d759f23d37e5060e023b9888cbbd7
"""
def config:schema:A = "int"
def config:schema:B = "sha-1"
def output = load_csv[config]
//output>
// (:A, 2, 1)
// (:A, 3, 2)
// (:A, 4, 3)
// (:B, 2, (:rel, :base, :SHA1, 17930511166010156306237819770844488478, 2139004524))
// (:B, 3, (:rel, :base, :SHA1, 22239876921550541361475316713022684995, 3047681493))
// (:B, 4, (:rel, :base, :SHA1, 32548687738050047961766682367612691385, 2290924503))JSON export formats SHA-1 values automatically to the standard string representation.
sha1_from_string
View sourcesha1_from_string(s in String, v in SHA1)Parse a SHA-1 string (in hexadecimal format) to a SHA1 value.
Example:
with rel:base use sha1_from_string
def output = sha1_from_string["0d7d4a744fd92effd1ed88e48ac8231e7f7e9e6c"]
//output> (:rel, :base, :SHA1, 17930511166010156306237819770844488478, 2139004524)Date
View sourceDate(d)
^Date(n, d)The Date data type representing a date in days of the proleptic Gregorian calendar.
The type relation Date checks if d is of type Date.
The constructor ^Date creates a date d of n days in the
Gregorian calendar starting at 0000-12-31, which is “day 0”.
Parameters
| Parameter | Type | Description |
|---|---|---|
d | Date | Date variable. |
n | Integer | The value of the Date data type, in days of the Gregorian calendar. |
Explanation
To use the ^Date(n, d) constructor, one has to specify all arguments and partial application, ^Date[n], can’t be used due to the overloaded nature of the ^Date constructor.
Examples
Construct a date from the duration in days.
def output(d) = ^Date(734638, d) // 734638 days since 0000-12-31
//output> 2012-05-15Construct a date from its parts (year, month, day).
^Date[2012, 5, 15]
//output> 2012-05-15Subtract two date literals. The result is of type Day.
def output = 2012-06-15 - 2012-05-15
//output> 31DateTime
View sourceDateTime(dt)
^DateTime(n, dt)The DateTime data type representing an instant in milliseconds of the proleptic
Gregorian calendar.
The type relation DateTime checks if dt is of type DateTime.
The constructor ^DateTime creates an instant d of n milliseconds in the
Gregorian calendar, where the reference timestamp 0000-12-31T00:00:00Z.
Parameters
| Parameter | Type | Description |
|---|---|---|
dt | DateTime | DateTime variable. |
n | Integer | The value of the DateTime data type, in milliseconds of the Gregorian calendar. |
Explanation
To use the ^DateTime(n, d) constructor, one has to specify all arguments and partial application, ^DateTime[n], can’t be used due to the overloaded nature of the ^DateTime constructor.
Examples
Construct a datetime from the duration in milliseconds.
def output(dt) = ^DateTime(63472766399000, dt)
//output> 2012-05-15T11:59:59.000ZConstruct a datetime from its parts (year, month, day, hour, minute, second, millisecond, timezone).
^DateTime[2012, 5, 15, 11, 59, 59, 0, "UTC"]
//output> 2012-05-15T11:59:59.000ZSubtract two datetime literals. The result is of type Millisecond.
def output = 2012-05-15T00:00:00Z - 2012-05-14T00:00:00Z
//output> 86400000Year
View sourceYear(p)
^Year(n, p)A period that spans n years. The period is given in units of Year.
The type relation rel:base:Year checks if p is of type Year.
The constructor ^Year maps the integer n to the corresponding Year period p.
Parameters
| Parameter | Type | Description |
|---|---|---|
p | Year | A period representing n years. |
n | Integer | The number of the years represented by p. |
Explanation
To use the rel:base:Year(p) type relation, one must include the rel:base module name.
Examples
Add 10 years to a datetime.
datetime_add[unix_epoch, ^Year[10]]
//output> 1980-01-01T00:00:00.000ZAdd two Year periods together.
def output = ^Year[10] + ^Year[2]
//output> 12Month
View sourceMonth(p)
^Month(n, p)A period that spans n months. The period is given in units of Month.
The type relation rel:base:Month checks if p is of type Month.
The constructor ^Month maps the integer n to the corresponding Month period p.
Parameters
| Parameter | Type | Description |
|---|---|---|
p | Month | A period representing n months. |
n | Integer | The number of the months represented by p. |
Explanation
To use the rel:base:Month(p) type relation, one must include the rel:base module name.
Examples
Add 10 months to a datetime.
datetime_add[unix_epoch, ^Month[10]]
//output> 1970-11-01T00:00:00.000ZAdd two Month periods together.
def output = ^Month[10] + ^Month[2]
//output> 12Week
View sourceWeek(p)
^Week(n, p)A period that spans n weeks. The period is given in units of Week.
The type relation rel:base:Week checks if p is of type Week.
The constructor ^Week maps the integer n to the corresponding Week period p.
Parameters
| Parameter | Type | Description |
|---|---|---|
p | Week | A period representing n weeks. |
n | Integer | The number of the weeks represented by p. |
Explanation
To use the rel:base:Week(p) type relation, one must include the rel:base module name.
Examples
Add 10 weeks to a datetime.
datetime_add[unix_epoch, ^Week[10]]
//output> 1970-03-12T00:00:00.000ZAdd two Week periods together.
def output = ^Week[10] + ^Week[2]
//output> 12Day
View sourceDay(p)
^Day(n, p)A period that spans n days. The period is given in units of Day.
The type relation rel:base:Day checks if p is of type Day.
The constructor ^Day maps the integer n to the corresponding Day period p.
Parameters
| Parameter | Type | Description |
|---|---|---|
p | Day | A period representing n days. |
n | Integer | The number of the days represented by p. |
Explanation
To use the rel:base:Day(p) type relation, one must include the rel:base module name.
Examples
Add 10 days to a datetime.
datetime_add[unix_epoch, ^Day[10]]
//output> 1970-01-11T00:00:00.000ZAdd two Day periods together.
def output = ^Day[10] + ^Day[2]
//output> 12Hour
View sourceHour(p)
^Hour(n, p)A period that spans n hours. The period is given in units of Hour.
The type relation rel:base:Hour checks if p is of type Hour.
The constructor ^Hour maps the integer n to the corresponding Hour period p.
Parameters
| Parameter | Type | Description |
|---|---|---|
p | Hour | A period representing n hours. |
n | Integer | The number of the hours represented by p. |
Explanation
To use the rel:base:Hour(p) type relation, one must include the rel:base module name.
Examples
Add 10 hours to a datetime.
datetime_add[unix_epoch, ^Hour[10]]
//output> 1970-01-01T10:00:00.000ZAdd two Hour periods together.
def output = ^Hour[10] + ^Hour[2]
//output> 12Minute
View sourceMinute(p)
^Minute(n, p)A period that spans n minutes. The period is given in units of Minute.
The type relation rel:base:Minute checks if p is of type Minute.
The constructor ^Minute maps the integer n to the corresponding Minute period p.
Parameters
| Parameter | Type | Description |
|---|---|---|
p | Minute | A period representing n minutes. |
n | Integer | The number of the minutes represented by p. |
Explanation
To use the rel:base:Minute(p) type relation, one must include the rel:base module name.
Examples
Add 100 minutes to a datetime.
datetime_add[unix_epoch, ^Minute[100]]
//output> 1970-01-01T01:40:00.000ZAdd two Minute periods together.
def output = ^Minute[10] + ^Minute[2]
//output> 12Second
View sourceSecond(p)
^Second(n, p)A period that spans n seconds. The period is given in units of Second.
The type relation rel:base:Second checks if p is of type Second.
The constructor ^Second maps the integer n to the corresponding Second period p.
Parameters
| Parameter | Type | Description |
|---|---|---|
p | Second | A period representing n seconds. |
n | Integer | The number of the seconds represented by p. |
Explanation
To use the rel:base:Second(p) type relation, one must include the rel:base module name.
Examples
Add 100 seconds to a datetime.
datetime_add[unix_epoch, ^Second[100]]
//output> 1970-01-01T00:01:40.000ZAdd two Second periods together.
def output = ^Second[10] + ^Second[2]
//output> 12Millisecond
View sourceMillisecond(p)
^Millisecond(n, p)A period that spans n milliseconds. The period is given in units of Millisecond ( seconds).
The type relation rel:base:Millisecond checks if p is of type Millisecond.
The constructor ^Millisecond maps the integer n to the corresponding Millisecond period p.
Parameters
| Parameter | Type | Description |
|---|---|---|
p | Millisecond | A period representing n milliseconds. |
n | Integer | The number of the milliseconds represented by p. |
Explanation
To use the rel:base:Millisecond(p) type relation, one must include the rel:base module name.
Examples
Add 20 thousand milliseconds (aka 20 s) to a datetime.
datetime_add[unix_epoch, ^Millisecond[20 * 10^3]]
//output> 1970-01-01T00:00:20.000ZAdd two Millisecond periods together.
def output = ^Millisecond[10] + ^Millisecond[2]
//output> 12Microsecond
View sourceMicrosecond(p)
^Microsecond(n, p)A period that spans n microseconds. The period is given in units of Microsecond ( seconds).
The type relation rel:base:Microsecond checks if p is of type Microsecond.
The constructor ^Microsecond maps the integer n to the corresponding Microsecond period p.
Parameters
| Parameter | Type | Description |
|---|---|---|
p | Microsecond | A period representing n microseconds. |
n | Integer | The number of the microseconds represented by p. |
Explanation
To use the rel:base:Microsecond(p) type relation, one must include the rel:base module name.
Examples
Add 5 million microseconds (aka 5 s) to a datetime.
datetime_add[unix_epoch, ^Microsecond[5 * 10^6]]
//output> 1970-01-01T00:00:05.000ZAdd two Microsecond periods together.
def output = ^Microsecond[10] + ^Microsecond[2]
//output> 12Nanosecond
View sourceNanosecond(p)
^Nanosecond(n, p)A period that spans n nanoseconds. The period is given in units of Nanosecond ( seconds).
The type relation rel:base:Nanosecond checks if p is of type Nanosecond.
The constructor ^Nanosecond maps the integer n to the corresponding Nanosecond period p.
Parameters
| Parameter | Type | Description |
|---|---|---|
p | Nanosecond | A period representing n nanoseconds. |
n | Integer | The number of the nanoseconds represented by p. |
Explanation
To use the rel:base:Nanosecond(p) type relation, one must include the rel:base module name.
Examples
Add 20 million nanoseconds (aka 20 ms) to a datetime.
def dt = parse_datetime["2020-01-01 01:00:00.001", "Y-m-d H:M:S.sss"]
def output = dt + ^Nanosecond[20 * 10^6]
//output> 2020-01-01T01:00:00.021.000ZAdd two Nanosecond periods together.
def output = ^Nanosecond[10] + ^Nanosecond[2]
//output> 12Module: rel:bignum
View sourceBigInteger
View source Type for arbitrary precision integers.
A Rel representation of the GMP integer type, as in https://gmplib.org/manual/Integer-Internals (opens in a new tab)
The Int8 is a sign (+/- 1) and the String is GMP’s “array of limbs” (a little-endian byte representation of abs(x)):