Skip to content

The Standard Library (stdlib)

Broad collection of Rel relations that perform essential and commonly used tasks.

^Char

View source
^Char(y, x)

Construct a Char, x, from its corresponding UInt32 value, y.

^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-01

For 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.000Z

For 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.

^Day

View source
^Day[n]

Create a period of n days.

^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.

^Hour

View source
^Hour[n]

Create a period of n hours.

^Microsecond

View source
^Microsecond[n]

Create a period of n microseconds.

^Millisecond

View source
^Millisecond[n]

Create a period of n milliseconds.

^Minute

View source
^Minute[n]

Create a period of n minutes.

^Month

View source
^Month[n]

Create a period of n months.

^Nanosecond

View source
^Nanosecond[n]

Create a period of n nanoseconds.

^Second

View source
^Second[n]

Create a period of n seconds.

^Week

View source
^Week[n]

Create a period of n weeks.

^Year

View source
^Year[n]

Create a period of n years.

¬

View source
not F
¬F

Logical negation, for boolean (arity 0, true or false) argument F.

View source
F and G
F  G

Logical and (conjunction).

View source
F or G
F  G

Logical or (disjunction), for boolean (arity 0, true or false) arguments F and G.

View source
F  G

Relational inequality, see equal.

abs

View source
abs[x]

The absolute value of x.

Examples:

abs[-2] = 2
abs[-2.0] = 2.0

acos

View source
acos[x]
acos(x, ac)

Arccosine of x. ac is the arccosine of x given in radians.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Cosine of ac. Must be grounded.
acFloatBinary[#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.5707963267948966

Calculate the arccosine of -1 using full expression:

def output(x) = acos(-1, x)
//output> 3.141592653589793

Confirm that 1.5707963267948966 is the arccosine of 0:

def output = acos(0, 1.5707963267948966)
//output> ()  // true

See Also

sin, cos, asin, asinh, acosh, sinh, cosh, and haversine.

acosh

View source
acosh[x]
acosh(x, ach)

Hyperbolic arccosine. ach is the hyperbolic arccosine of x.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Hyperbolic cosine of ach. Must be grounded.
achFloatBinary[#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.192925985263684

Calculate the hyperbolic arccosine of 180 using full expression:

def output(x) = acosh(180, x)
//output> 5.886096315311465

Confirm that 5.192925985263684 is the hyperbolic arccosine of 90:

def output = acosh(90, 5.192925985263684)
//output> ()  // true

See Also

sin, cos, asin, acos, asinh, acosh, sinh, and haversine.

acot

View source
acot[x]
acot(x, act)

Arccotangent. act is the arccotangent of x.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Cotangent of act. Must be grounded.
actFloatBinary[#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.7853981633974483

Calculate the arccotangent of -1 using full expression:

def output(x) = acot(-1, x)
//output = -0.7853981633974483

Confirm that 0.7853981633974483 is the arccotangent of 1:

def output = acot(1, 0.7853981633974483)
//output> ()  // true

See Also

tan, atan, atan2, cot, tanh, and atanh.

add

View source
add[x, y]
add(x, y, s)
x + y

Addition of two numbers. Addition of a DateTime/Date, x, with a time duration y.

Parameters

Numeric Data

ParameterTypeDescription
xNumberFirst summand.
yNumberSecond summand.
sNumberSum x + y.

Not all numeric values can be mixed with each other. The following combinations work:

xys
NumberSame as xSame as x
Rational, FixedDecimalSignedInteger[#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:

  • x and y.
  • x and s.
  • y and s.

Time Data

ParameterTypeDescription
xDate, DateTime, date period, time periodFirst summand.
yDate, DateTime, date period, time periodSecond summand.
sDate, DateTime, date period, time periodSum x + y.

The following combinations work:

xys
date period, time periodSame date period, time period as xSame date period, time period as x
date period, time periodDateTimeDateTime
DateTimedate period, time periodDateTime
date periodDateDate
Datedate periodDate

Two of the three arguments need to be grounded. Valid grounding combinations are as follows:

  • x and y.
  • x and s.
  • y and s.

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> 3

Add an integer and a float using add:

def output = add[1, 2.5]
//output> 3.5

Add two floats using full expression:

def output(x) = add(1.7, 2.8, x)
//output> 4.5

Add integer to a rational:

def output = 1 + rational[16][2, 3]
//output> 5/3

Addition 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-07

Add seconds together:

def output = ^Second[1] + ^Second[2]
//output> 3

See Also

subtract, divide, and multiply.

Any

View source
Any(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 source
approx_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

ParameterTypeDescription
toleranceSignedInteger[#64] or FloatBinary[#64]Tolerance of the approximation. A positive number. Must be grounded.
xNumberA valid number. Must be the same data type as y. Must be grounded.
yNumberA 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> ()  // true

Approximate equality determined as false:

def output = approx_eq(0.01, 0.1, 0.15)
//output>    // false

See Also

equal, eq, approx_equal, and full_relation_approx_equal.

approx_equal

View source
approx_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

ParameterTypeDescription
toleranceSignedInteger[#64] or FloatBinary[#64]A positive integer or float. Must be grounded.
RRelationA relation with corresponding keys and last elements that can be compared to S. Must be grounded.
SRelationA 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> ()  // true

Approximate 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>    // false

Approximate 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>    // false

Approximate 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>    // false

See Also

full_relation_approx_equal, approx_eq, equal, and eq.

argmax

View source
argmax[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

ParameterTypeDescription
RRelationA relation whose tuples contain key-value pairs. Must be grounded.
amNumberA 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, maximum, min, argmax, sum, product, and average.

ArgMax

View source
ArgMax[R]

Please use argmax[R]. Deprecates in near future

argmin

View source
argmin[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

ParameterTypeDescription
RRelationSource relation. Must be grounded.
amAnyA 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

argmax, minimum, min, argmax, sum, product, and average.

ArgMin

View source
ArgMin[R]

Please use argmin[R]. Deprecates in near future

arity

View source
arity[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
//        2

Arity 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 source
asin[x]
asin(x, as)

Arcsine of x. ac is the arcsine of x given in radians.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Sine of as. Must be grounded.
asFloatBinary[#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.5707963267948966

Calculate the arcsine of -.5 using full expression:

def output(x) = asin(-.5, x)
//output> -0.5235987755982989

Confirm that 1.5707963267948966 is the arcsine of 1:

def output = asin(1, 1.5707963267948966)
//output> ()  // true

See Also

sin, cos, acos, asinh, acosh, sinh, cosh, and haversine.

asinh

View source
asinh[x]
asinh(x, ash)

Hyperbolic arcsine. ash is the hyperbolic arcsine of x.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Hyperbolic sine of ash. Must be grounded.
ashFloatBinary[#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.99822295029797

Calculate the hyperbolic arcsine of -1 using full expression:

def output(x) = asinh(-1, x)
//output> -0.881373587019543

Confirm that 2.99822295029797 is the hyperbolic arcsine of 10:

def output = asinh(10, 2.99822295029797)
//output> ()  // true

See Also

sin, cos, asin, acos, acosh, sinh, cosh, and haversine.

atan

View source
atan[x]
atan(x, at)

Arctangent. at is the arctangent of x in radians.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Tangent of at. Must be gounded.
atFloatBinary[#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.6657737500283538

Convert degrees to radians and calculate arctangent using full expression:

def x = deg2rad[90]
def output(at) = atan(x, at)
//output> 1.0038848218538872

Confirm that 0.6657737500283538 is the tangent of π/4:

def output = atan(pi_float64/4, 0.6657737500283538)
//output> ()  // true

See Also

tan, atan2, cot, acot, tanh, and atanh.

atan2

View source
atan2[y, x]
atan2(y, x, at)

Arctangent. at is the arctangent of the quotient y/x in radians.

Parameters

ParameterTypeDescription
yFloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64]yy coordinate of the 2D point (x,y)(x, y). Must be gounded.
xUnsignedInteger[#64], SignedInteger[#64], FloatBinary[#64]xx coordinate of the 2D point (x,y)(x, y). Must be gounded.
atFloatBinary[#64]Arctangent of x.

Explanation

Arctangent is sometimes called “inverse tangent.” The parameters x and y can be thought of as the xx and yy coordinates of the 2D point (x,y)(x, y).

Examples

Calculate the arctangent of 50:

def output = atan2[100, 2.0]
//output> 1.550798992821746

See Also

atan, tan, cot, acot, tanh, and atanh.

atanh

View source
atanh[x]
atanh(x, ath)

Hyperbolic arctangent. ath is the hyperbolic arctangent of x.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Hyperbolic tangent of ath. Must be grounded.
athFloatBinary[#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.8673005276940532

Calculate the hyperbolic arctangent of .7 using full expression:

def output(x) = atanh(.7, x)
//output> 0.8673005276940532

Confirm that -0.8673005276940532 is the hyperbolic arctangent of -.7:

def output = atanh(-.7, -0.8673005276940532)
//output> ()  // true

See Also

tan, atan, atan2, cot, acot, tanh, and atanh.

average

View source
average[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 source
bigint[i]

Create a BigInteger value from the given integer.

Examples:

string[factorial[bigint[50]]] = "30414093201713378043612608166064768844377641568960512000000000000"

bigint_int64_convert

View source
Convert a BigInteger to an Int64.

Examples:

bigint_int64_convert[bigint[50]] = 50

bitwise_and

View source
bitwise_and[x, y]
bitwise_and(x, y, z)

Bitwise and of two integers.

Parameters

ParameterTypeDescription
xSignedInteger, UnsignedIntegerLeft operand. Must be grounded.
ySignedInteger, UnsignedIntegerRight operand. Must be grounded.
zSignedInteger, UnsignedIntegerThe bitwise and of x and y.

Not all numeric values can be mixed with each other. The following combinations work:

xyz
SignedInteger, UnsignedIntegerSame as x.Same as x.
SignedInteger, UnsignedIntegerSignedInteger[#64], UnsignedInteger[#32]Same as x.

Examples

Bitwise and of 3 and 2:

def output = bitwise_and[3, 2]
//output> 2

Bitwise and of two unsigned integers using full expression:

def output(z) = bitwise_and(0x11100, 0x00101, z)
//output> 256

Bitwise 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 source
bitwise_left_shift[x, y]
bitwise_left_shift(x, y, z)

Bitwise left shift of an integer x by y bits.

Parameters

ParameterTypeDescription
xSignedInteger, UnsignedIntegerOperand. Must be grounded.
ySignedInteger, UnsignedIntegereBits for left shift. Must be grounded.
zSignedInteger, UnsignedIntegerThe bitwise left shift of x and y.

Not all numeric values can be mixed with each other. The following combinations work:

xyz
SignedInteger, UnsignedIntegerSame as x.Same as x.
SignedInteger, UnsignedIntegerSignedInteger[#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> 16

Bitwise left shift of 1 by 10 bits using full expression:

def output(z) = bitwise_left_shift(1, 10, z)
//output> 1024

Bitwise left shift of 0xf by 1 bit:

def output = bitwise_left_shift[0xF, 1]
//output> 30

Bitwise left shift of unsigned integer:

def output = bitwise_left_shift[uint[64, 4028], 1]
//output> 8056

See Also

bitwise_and, bitwise_or, bitwise_xor, bitwise_right_shift, bitwise_unsigned_right_shift, and bitwise_not.

bitwise_not

View source
bitwise_not[x]
bitwise_not(x, z)

Bitwise not of an integer.

Parameters

ParameterTypeDescription
xSignedInteger, UnsignedIntegerOperand. Must be grounded.
zSignedInteger, UnsignedIntegerThe bitwise not of x.

Not all numeric values can be mixed with each other. The following combinations work:

xz
SignedInteger, UnsignedIntegerSame as x.Same as x.

Examples

Bitwise not of -9:

def output = bitwise_not[-9]
//output> 8

Bitwise not of 8 using full expression:

def output(z) = bitwise_not(8, z)
//output> -9

Bitwise not of 0x00011:

def output = bitwise_not[0x00011]
//output> 4294967278

See Also

bitwise_and, bitwise_or, bitwise_xor, bitwise_left_shift, bitwise_right_shift, and bitwise_unsigned_right_shift.

bitwise_or

View source
bitwise_or[x, y]
bitwise_or(x, y, z)

Bitwise or of two integers.

Parameters

ParameterTypeDescription
xSignedInteger, UnsignedIntegerLeft operand. Must be grounded.
ySignedInteger, UnsignedIntegerRight operand. Must be grounded.
zSignedInteger, UnsignedIntegerThe bitwise or of x and y.

Not all numeric values can be mixed with each other. The following combinations work:

xyz
SignedInteger, UnsignedIntegerSame as x.Same as x.
SignedInteger, UnsignedIntegerSignedInteger[#64], UnsignedInteger[#32]Same as x.

Examples

def output = bitwise_or[3, 2]
//output> 3

Bitwise or of 0x00011 and 0x11100 using full expression:

def output(z) = bitwise_or(0x00011, 0x11100, z)
//output> 69905

Bitwise xor of two unsigned integers:

def output = bitwise_or[uint[64, 1024], uint[64, 2048]]
//output> 3072

See Also

bitwise_and, bitwise_xor, bitwise_left_shift, bitwise_right_shift, bitwise_unsigned_right_shift, and bitwise_not.

bitwise_right_shift

View source
bitwise_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

ParameterTypeDescription
xSignedInteger, UnsignedIntegerOperand. Must be grounded.
ySignedInteger, UnsignedIntegerBits for right shift. Must be grounded.
zSignedInteger, UnsignedIntegerThe bitwise right shift of x and y.

Not all numeric values can be mixed with each other. The following combinations work:

xyz
SignedInteger, UnsignedIntegerSame as x.Same as x.
SignedInteger, UnsignedIntegerSignedInteger[#64], UnsignedInteger[#32]Same as x.

Examples

Bitwise right shift of 1024 by 1 bit:

def output = bitwise_right_shift[1024, 1]
//output> 512

Bitwise right shift of -1024 by 1 bit using full expression:

def output(z) = bitwise_right_shift(-1024, 1, z)
//output> -512

Bitwise right shift of unsigned integer by 2 bits:

def output = bitwise_right_shift[uint[64, 2048], 2]
//output> 512

See Also

bitwise_and, bitwise_or, bitwise_xor, bitwise_left_shift, bitwise_unsigned_right_shift, and bitwise_not.

bitwise_unsigned_right_shift

View source
bitwise_unsigned_right_shift[x, y]
bitwise_unsigned_right_shift(x, y, z)

Bitwise unsigned right shift of an integer by y bits.

Parameters

ParameterTypeDescription
xSignedInteger, UnsignedIntegerOperand. Must be grounded.
ySignedInteger, UnsignedIntegerBits for unsigned right shift. Must be grounded.
zSignedInteger, UnsignedIntegerThe bitwise unsigned right shift of x and y.

Not all numeric values can be mixed with each other. The following combinations work:

xyz
SignedInteger, UnsignedIntegerSame as x.Same as x.
SignedInteger, UnsignedIntegerSignedInteger[#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> 4

Bitwise unsigned right shift of -8 by 2 bits:

def output(z) = bitwise_unsigned_right_shift(-8, 2, z)
//output> 4611686018427387902

Bitwise unsigned right shift of unsigned integer by 3 bits:

def output = bitwise_unsigned_right_shift[uint[64, 8], 3]
//output> 1

See Also

bitwise_and, bitwise_or, bitwise_xor, bitwise_left_shift, bitwise_right_shift, and bitwise_not.

bitwise_xor

View source
bitwise_xor[x, y]
bitwise_xor(x, y, z)

Bitwise xor (exclusive or) of two integers.

Parameters

ParameterTypeDescription
xSignedInteger, UnsignedIntegerLeft operand. Must be grounded.
ySignedInteger, UnsignedIntegerRight operand. Must be grounded.
zSignedInteger, UnsignedIntegerThe bitwise xor of x and y.

Not all numeric values can be mixed with each other. The following combinations work:

xyz
SignedInteger, UnsignedIntegerSame as x.Same as x.
SignedInteger, UnsignedIntegerSignedInteger[#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> 69905

Bitwise xor of two unsigned integers:

def output = bitwise_xor[uint[64, 1024], uint[64, 2048]]
//output> 3072

See Also

bitwise_and, bitwise_or, bitwise_left_shift, bitwise_right_shift, bitwise_unsigned_right_shift, and bitwise_not.

Boolean

View source
Boolean(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 source
boolean_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_false

View source
boolean_false(x)

Holds if x is a Boolean of value false.

boolean_not

View source
boolean_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 source
boolean_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)

boolean_true

View source
boolean_true(x)

Holds if x is a Boolean of value true.

bottom

View source
bottom[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

ParameterTypeDescription
RRelationSource relation. Must be grounded.
kIntNumber of tuples to sort from the bottom of R. Must be grounded.
indexIntThe new enumeration index starting at 1.
x...TupleA 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, 3

See Also

top, enumerate, sort, and reverse_sort.

byte

View source
byte[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] = 0xb8

Abstracting 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 source
capture_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 source
capture_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 source
cart[R, S]
R × S

Cartesian product.

Examples:

def output = 1 ✕ 2
//output> (1,2)
def output = {1; 2} ✕ {3; 4}
//output> (1,3)
//        (1,4)
//        (2,3)
//        (2,4)

cbrt

View source
cbrt[x]

The cube root of x.

Example:

cbrt[27] = 3.0

ceil

View source
ceil[x]
ceil(x, c)

Round up to the nearest integer.

Parameters

ParameterTypeDescription
xNumberNumber to be rounded up. Must be grounded.
cSignedInteger[#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.0

Calculate ceil for negative float using full expression:

def output(c) = ceil(-4.5, c)
//output> -4.0

Calculate ceil for rational:

def output = ceil[rational[64, 8, 3]]
//output> 3/1

See Also

floor, floor_to_int, trunc, trunc_to_int, and round.

char

View source
char[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 source
Char(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 source
clamp[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

ParameterTypeDescription
lowSame as value.Lower bound. Must be grounded.
highSame as value.Upper bound. Must be grounded.
valueNumberValue to be clamped. Must be grounded.
clampedSame as valuevalue 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:

clamped={low if valuelowvalue if low<value<highhigh if valuehigh\texttt{clamped} = \begin{cases} \texttt{low} & \text{ if } \texttt{value} \leq \texttt{low}\\ \texttt{value} & \text{ if } \texttt{low} < \texttt{value} < \texttt{high}\\ \texttt{high} & \text{ if } \texttt{value} \geq \texttt{high} \end{cases}

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
//        4

Clamp 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/27

See Also

range.

complement

View source
complement[R]

The complement of the relation R.

concat

View source
concat[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 source
contains(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')                   // false

cos

View source
cos[x]
cos(x, c)

Cosine of of x, where x is an angle given in radians.

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Angle in radians. Must be grounded.
cFloatBinary[#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.8660254037844387

Calculate the cosine of π/4 using full expression:

def output(x) = cos(pi_float64/4, x)
//output> 0.7071067811865476

Confirm that 0.5000000000000001 is the cosine of π/3:

def output = cos(pi_float64/3, 0.5000000000000001)
//output> ()  // true

See Also

sin, asin, acos, asinh, acosh, sinh, cosh, and haversine.

cosh

View source
cosh[x]
cosh(x, ch)

Hyperbolic cosine. ch is the hyperbolic cosine of x.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Hyperbolic angle. Must be grounded.
chFloatBinary[#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.5430806348152437

Calculate the hyperbolic cosine of -7 using full expression:

def output(x) = cosh(-7, x)
//output> 548.317035155212

Confirm that 1.5430806348152437 is the hyperbolic cosine of 1:

def output = cosh(1, 1.5430806348152437)
//output> ()  // true

See Also

sin, cos, asin, acos, asinh, sinh, cosh, and haversine.

cot

View source
cot[x]
cot(x, ct)

Cotangent. ct is the cotangent of x, where x is in radians.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Angle in radians. Must be grounded.
ctFloatBinary[#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.0000000000000002

Convert degrees to radians and calculate cotangent using full expression:

def x = deg2rad[90]
def output(t) = cot(x, t)
//output> 6.123233995736766e-17

Confirm that 1.0000000000000002 is the cotangent of π/4:

def output = cot(pi_float64/4, 1.0000000000000002)
//output> ()  // true

See Also

tan, atan, atan2, acot, tanh, and atanh.

count

View source
count[R]
count(R, n)

Count the number n of tuples contained in the relation R.

Parameters

ParameterTypeDescription
RRelationA general relation. Must be grounded.
nIntegerNumber 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> 3

Count a singleton relation:

def output = count[5]
//output> 1

Test if employees contains three tuples:

def output = count(employees, 3)
//output> ()  // true

See Also

argmax, argmin, average, bottom, top, first, last, max, min, mode, and product.

csv_string

View source
csv_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 the Int indices indicate the column order, and the column name is provided as a Symbol (of type RelName). This option overrides the default (or existing) header names.
    • :header_row: An Int that 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: An Int that specifies the row from where to start parsing values into relations.
    • :missingstrings: One or multiple String values that should be interpreted as missing values. By default, only empty fields are considered missing.
    • :delim: An ASCII Char that delimits individual fields while parsing. Defaults to ','.
    • :quotechar: An ASCII Char that signals a “quoted” field while parsing. Defaults to '"'.
    • :escapechar: An ASCII Char used to “escape” quotechars and other escapechars 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

load_csv, export_csv, Char, int, RelName, String.

current_transaction_id

View source
current_transaction_id

The 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

View source
Date(x)

Holds if x is a Date.

date_add

View source
date_add[d, period]
d + period

Add 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-11

date_day

View source
date_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] = 31

date_dayname

View source
date_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 source
date_dayofquarter[d]

Day of quarter

Example:

def d = parse_date["2014-01-31", "Y-m-d"]
date_dayofquarter[d] = 31

date_dayofweek

View source
date_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] = 5

date_dayofweekofmonth

View source
date_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 month

date_dayofyear

View source
date_dayofyear[d]

Day of year

Example:

def t = parse_date["2014-01-31", "Y-m-d"]
def output = date_dayofyear[t]
//output> 31

date_daysinmonth

View source
date_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] = 29

date_isleapyear

View source
date_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> ()  // true

date_month

View source
date_month[d]

Month of a Date, as an integer between 1 and 12.

date_monthname

View source
date_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 source
date_quarterofyear[d]

Quarter to year

Example:

def d = parse_date["2014-01-31", "Y-m-d"]
date_quarterofyear[d] = 1

date_subtract

View source
date_subtract[date, period]
date - period

Subtract 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-26

date_week

View source
date_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"]] = 1

date_year

View source
date_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 source
dates_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

View source
DateTime(x)

Holds if x is a DateTime.

datetime_add

View source
datetime_add[dt, period]
dt + period

Add 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.000Z

datetime_day

View source
datetime_day(dt, tz, d)

Compute the day of the month d of a timestamp dt in the timezone tz.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
tzStringTime zone. Must be grounded.
dIntDay 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> 31

See Also

date_day, datetime_year, datetime_month, datetime_week, and datetime_hour.

datetime_day_UTC

View source
datetime_day_UTC(dt, d)

Compute the day of the month d of a timestamp dt assuming the UTC timezone.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
dIntDay 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> 31

See Also

datetime_month_UTC, datetime_week_UTC, datetime_day, and date_day.

datetime_dayname

View source
datetime_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 source
datetime_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"] = 31

datetime_dayofweek

View source
datetime_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"] = 4

datetime_dayofweekofmonth

View source
datetime_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"] = 5

datetime_dayofyear

View source
datetime_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"] = 89

datetime_daysinmonth

View source
datetime_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"] = 28

datetime_hour

View source
datetime_hour(dt, tz, h)

Compute the hour of the day h of a timestamp dt in the timezone tz.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
tzStringTime zone. Must be grounded.
hIntHour 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> 22

See Also

datetime_minute, datetime_second, and datetime_day.

datetime_hour_UTC

View source
datetime_hour_UTC(dt, h)

Compute the hour h of a timestamp dt assuming the UTC timezone.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
hIntHour 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> 20

See Also

datetime_day_UTC, datetime_minute_UTC, and datetime_hour.

datetime_isleapyear

View source
datetime_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> ()  // true

datetime_minute

View source
datetime_minute(dt, tz, m)

Compute the minute part of a timestamp dt in the timezone tz.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
tzStringTime zone. Must be grounded.
mIntMinute.

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> 45

See Also

datetime_hour and datetime_second.

datetime_minute_UTC

View source
datetime_minute_UTC(dt, m)

Compute the minute m of a timestamp dt assuming the UTC timezone.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
mIntMinute.

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> 0

See Also

datetime_day_UTC, datetime_hour_UTC, and datetime_minute.

datetime_month

View source
datetime_month(dt, tz, m)

Compute the month m of a timestamp dt in the timezone tz.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
tzStringTime zone. Must be grounded.
mIntMonth.

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> 12

See Also

date_month, datetime_year, datetime_week, and datetime_day.

datetime_month_UTC

View source
datetime_month_UTC(dt, m)

Compute the month m of a timestamp dt assuming the UTC timezone.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
mIntMonth.

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> 12

See Also

datetime_year_UTC, datetime_month, and date_month.

datetime_monthname

View source
datetime_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 source
datetime_now(dt)

The current time dt at the beginning of the transaction.

Parameters

ParameterTypeDescription
dtDateTimeDate 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.263Z

datetime_quarterofyear

View source
datetime_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"] = 1

datetime_second

View source
datetime_second(dt, s)

Compute the second s of a timestamp dt.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
sIntSecond.

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> 3

See Also

datetime_hour and datetime_second.

datetime_subtract

View source
datetime_subtract[dt, period]
dt - period

Subtract 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.000Z

datetime_to_nanoseconds

View source
datetime_to_nanoseconds[dt]

Convert datetime to nanoseconds since the epoch. Assumes dt is in UTC.

datetime_week

View source
datetime_week(dt, tz, w)

Compute the ISO week number (opens in a new tab) w of a timestamp dt in the timezone tz.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
tzStringTime zone. Must be grounded.
wIntISO 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> 52

See Also

date_week, datetime_year, datetime_month, and datetime_day.

datetime_week_UTC

View source
datetime_week_UTC(dt, w)

Compute the ISO week number (opens in a new tab) w of a timestamp dt assuming the UTC timezone.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
wIntISO 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> 52

See Also

datetime_month_UTC, datetime_day_UTC, datetime_week, and date_week.

datetime_year

View source
datetime_year(dt, tz, y)

Compute the year y of a timestamp dt in the timezone tz.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
tzStringTime zone. Must be grounded.
yIntYear.

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> 2020

See Also

date_year, datetime_month, datetime_week, and datetime_day.

datetime_year_UTC

View source
datetime_year_UTC(dt, y)

Compute the year y of a timestamp dt assuming the UTC timezone.

Parameters

ParameterTypeDescription
dtDateTimeDate and time of the current transaction. Must be grounded.
yIntYear.

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> 2023

See Also

datetime_month_UTC, datetime_year, and date_year.

datetimes_period_milliseconds

View source
datetimes_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 source
Day[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 source
decimal[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 source
decimal_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] = 64

decimal_int_convert

View source
decimal_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]] = false

decimal_precision

View source
decimal_precision[decimal]

The precision of a fixed-point decimal number.

Example:

def g = parse_decimal[#64, #2, "3.14"]
decimal_precision[g] = 2

decode_base16

View source
decode_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 source
decode_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 source
decode_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 source
default_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

left_override and right_override.

deg2rad

View source
deg2rad[d]
deg2rad(d, r)

Convert degrees to radians.

Parameters

ParameterTypeDescription
dFloat, Intr in degrees. Must be grounded.
rFloatd in radians.

Examples

Convert 180 degrees to radians:

def output = deg2rad[180]
//output> 3.141592653589793

Convert -90 degrees to radians using full expression:

def output = deg2rad[-90]
//output> -1.5707963267948966

denominator

View source
denominator[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] = 1

describe

View source
describe[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 source
despecialize[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> ()  // true

diff

View source
diff[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
//        4

disjoint

View source
disjoint(R, S)

R and S are disjoint if they have no fact in common.

divide

View source
divide[x, y]
divide(x, y, q)
x / y

Division of two numbers.

Parameters

ParameterTypeDescription
xNumberNumerator. Must be grounded.
yNumberDenominator. Must be grounded.
qNumberQuotient 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)):

xyq
FloatBinarySame as xSame as x
Rational, FixedDecimalNon-zero same as xSame as x
SignedInteger, UnsignedIntegerSignedInteger, UnsignedIntegerFloatBinary[#64]
FloatBinary[#64]NumberFloatBinary[#64]
NumberFloatBinary[#64]FloatBinary[#64]
SignedInteger, UnsignedIntegerSignedInteger[#64]FloatBinary[#64]
SignedInteger[#64]SignedInteger, UnsignedIntegerFloatBinary[#64]
FloatBinarySignedInteger[#64]Same as x
SignedInteger[#64]FloatBinarySame as y
FixedDecimalNon-zero SignedInteger, UnsignedIntegerSame as x
SignedInteger, UnsignedIntegerNon-zero FixedDecimalSame as y
RationalNon-zero SignedIntegerRational with the larger bitsize of x and y
SignedIntegerNon-zero RationalRational 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.0

Divide two rationals using /:

def output = rational[64, 8, 3] / rational[64, 5, 2]
//output> 16/15

Divide one float by another using divide:

def output = divide[8.4, 2.1]
//output> 4.0

Divide a rational by an integer using full expression:

def output(x) = divide(rational[16, 8, 3], 2, x)
//output> 4/3

docstring

View source
docstring[: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 source
domain[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')

dot_join

View source
dot_join[R, S]
R . S

Compose

double_metaphone

View source
double_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> rlxnl

empty

View source
empty(R)

Examples:

  • empty(1) is false
  • empty(true) is false
  • empty(false) is true

encode_base16

View source
encode_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 source
encode_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 source
encode_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 source
ends_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")    // false

Entity

View source
Entity(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 source
enumerate[R]
enumerate(R, index, x...)

Enumerate the tuples in the relation R from 1 to count[R].

Parameters

ParameterTypeDescription
RRelationRelation to be enumerated. Must be grounded.
indexIntThe new enumeration index starting at 1.
x...TuplesA 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:

  1. Tuples are first ordered by the data types in the first column, then second, and so on.
  2. Tuples with no data in the current column come first. For example, (Int) comes before (Int, Int).
  3. Within each column, types are put in alphabetical order. For example, Char precedes Date, which precedes FloatBinary.
  4. If types have parameters, they are ordered by parameters. For example, FloatBinary[#32] precedes FloatBinary[#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:

  1. Tuples are first sorted by the data values in the first column, then second, and so on.
  2. Tuples are ordered based on the intrinsic order of the data type.
    • Numeric data types: Sorting numerically. For example, 1 comes before 2.
    • Text-based data types: Char and String are 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: Date and DateTime are sorted so that older timestamps come first.

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 index

Enumerate 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 source
epoch_milliseconds[dt]

Milliseconds since Epoch time, as a value of type Int64.

eq

View source
eq(x, y)
x = y

Equality between scalar (single) values, such as integers, strings, symbols. (For equality between relations, use equal.)

Examples:

  • 1 = 1 is true.
  • :a = :a is true
  • "a" = "a" is true
  • 2 = 2.0 is false
  • 1 = "a" is false

equal

View source
equal(R, S)
F  G

Relational 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 source
erf[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.5204998778130465

erfinv

View source
erfinv[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.0

escape_regex_metachars

View source
escape_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 source
export_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=100 it will be exported into 10 partitions of roughly 100MB each. Set :partition_size=0 to suppress partitioning even for very large exports at the cost of export performance. By default, :partition_size=0 is used.
  • :compression: The algorithm that is used to compress the CSV output file. We only support gzip at 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 source
export_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 source
factorial[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 source
filepos[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 source
FilePos(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 source
filepos_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 source
first[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 source
FixedDecimal(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.1416

FixedDecimal_spread

View source
FixedDecimal_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.

ParameterTypeDescription
modeRelName:even or :ratio.
RRelationSource relation. Must be grounded.
valueFixedDecimalDecimal to be divided among tuples as spread.
x...TupleA tuple in R.
spreadFloatBinary[#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.046

Spread 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.4

Spread 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.304

Spread 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.0

See Also

int_spread_by_ratio, int_spread_by_even, and spread.

FixedPoint

View source
FixedPoint(x)

Holds if x is a fixed point number.

Parameters

ParameterTypeDescription
xFixedPointA 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.1416

See Also

FixedDecimal

FixedSizeInteger

View source
FixedSizeInteger(x)

Holds if x is a fixed size integer (signed or unsigned).

Parameters

ParameterTypeDescription
xFixedSizeIntegerA 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; 0x05

See Also

SignedInteger and UnsignedInteger

FixedSizeRational

View source
FixedSizeRational(x)

Holds if x is a fixed size rational (signed or unsigned).

Parameters

ParameterTypeDescription
xFixedSizeRationalA 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//7

See Also

SignedRational and Rational

float

View source
float[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 source
float_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] = false

float64

View source
float64[v]

The 64-bit floating point value from the number v, which must be a float.

FloatBinary

View source
FloatBinary(#nbits, x)

Holds if x is an `nbits’ floating point number.

Parameters

ParameterTypeDescription
#nbits#(Int)A specialized integer (must be a valid bit size).
xFloatBinaryA 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 source
Floating(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 source
FloatingPoint(x)

Holds if x is a floating point number.

Parameters

ParameterTypeDescription
xFloatingPointA 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.321

See Also

FloatBinary

floor

View source
floor[x]
floor(x, f)

Round down to the nearest integer toward negative infinity.

Parameters

ParameterTypeDescription
xNumberNumber to be rounded down. Must be grounded.
fNumberFloor 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.0

Calculate floor for negative decimal using full expression:

def output(f) = floor(-4.569, f)
//output> -5.0

Calculate floor for positive rational:

def output = floor[rational[64, 8, 3]]
//output> 2/1

See Also

floor_to_int, ceil, trunc, trunc_to_int, and round.

floor_divide

View source
floor_divide[x, y]
floor_divide(x, y, q)

Division of two numbers, rounding the result to the nearest integer toward negative infinity.

Parameters

ParameterTypeDescription
xNumberNumerator. Must be grounded.
yNumberDenominator. Must be grounded.
qNumberLargest integer less than or equal to x / y.

Not all numeric values can be mixed with each other. The following combinations work:

xyq
SignedInteger[#64]SignedInteger[#64]SignedInteger[#64]
SignedInteger[#64]FloatBinary[#64]FloatBinary[#64]
FloatBinary[#64]SignedInteger[#64], FloatBinary[#64]FloatBinary[#64]
RationalSignedInteger[#64]SignedInteger[#64]
FixedDecimalSignedInteger[#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> 2

Use floor division with full expression to divide a negative integer by a positive integer:

def output(q) = floor_divide(-5, 2, q)
//output> -3

Use floor division to divide a float by an integer:

def output = floor_divide[5.1, 2]
//output> 2.0

Confirm that floor_division[R] is empty when y = O:

def output = empty(floor_divide[5.1, 0])
//output> ()  // true

floor_to_int

View source
floor_to_int[x]
floor_to_int(x, f)

Convert float to integer using floor.

Parameters

ParameterTypeDescription
xFloatFloat to be converted to integer using floor. Must be grounded.
fIntFloor 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> 3

Convert 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> -4

Returns false because x is an integer:

def output = floor_to_int[3]
//output>    // false

See Also

floor, ceil, trunc, trunc_to_int, and round.

format_date

View source
format_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-12

For details on the format parameter, see the Julia documentation for Dates.DateFormat (opens in a new tab).

format_datetime

View source
format_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 source
formula_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 source
frequency[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

ParameterTypeDescription
RRelationA general relation. Must be grounded.
elemAnyElement whose frequency will be found.
freqNumberThe 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> 2

Find 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", 3

full_relation_approx_equal

View source
full_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.

ParameterTypeDescription
toleranceSignedInteger[#64] or FloatBinary[#64]A positive integer or float.
RRelationA relation whose arguments can be compared to S.
SRelationA 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> ()  // true

Approximate 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>    // false

See Also

approx_equal, approx_eq, equal, and eq.

function

View source
function(R)

Holds if R is a function.

ParameterTypeDescription
RRelationA 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> ()  // true

Evaluates to false:

def output = function({(1, 2); (1, 3)})
//output>    // false

Arity-3 function that evaluates to true:

def output = function({(1, 2, 3) ; (1, 3, 4)})
//output> ()  // true

Integrity constraint ensuring that R is a function:

ic R_is_a_function { function(R) }

See Also

domain and default_value.

geometric_mean

View source
geometric_mean[R]
geometric_mean(R, gm)

The geometric mean of the last element of each tuple in a relation R.

Parameters

ParameterTypeDescription
RRelationA relation whose tuples contain numeric data types. Must be grounded.
gmSignedInteger, FloatBinaryThe 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.936283427035352

Calculate 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.276527798701737

See Also

mean, harmonic_mean, weighted_mean, mode, max, min, sum, and product.

gt

View source
gt(x, y)
x > y

gt_eq

View source
gt_eq(x, y)
x  y
x >= y

harmonic_mean

View source
harmonic_mean[R]
harmonic_mean(R, hm)

The harmonic mean (hm) of the last elements of each tuple in a relation R.

Parameters

ParameterTypeDescription
RRelationA relation whose tuples contain numeric data types. Must be grounded.
hmNumberThe 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.44897959184

Calculate 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.229800388043014

Find 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.736842105263158

See Also

geometric_mean, weighted_mean, mean, mode, max, min, sum, and product.

hash

View source
hash[R]
hash(R, x..., h)

Hash each of the tuples in the relation and add it as a new column in the result.

Parameters

ParameterTypeDescription
RRelationRelation to be hashed. Must be grounded.
x...TuplesA tuple in R associated with hash.
hHashA 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, 59209653874858713274180299714158372840

Hash 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, 153679601071624610141668476986592179913

Hash 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, 153679601071624610141668476986592179913

Confirm 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> ()  // true

See Also

hash_value_uint128_convert, murmurhash3f, and murmurhash3f_with_seed.

Hash

View source
Hash(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> -107770920621774551289984725953057040743

hash_value_uint128_convert

View source
hash_value_uint128_convert[v]

Convert a HashValue v to UInt128.

hash128

View source
hash128[R]
hash128(R, x..., h)

Hash each of the tuples in the relation and add it as a new column in the result.

Parameters

ParameterTypeDescription
RRelationRelation to be hashed. Must be grounded.
x...TupleA tuple in R associated with hash.
hHashA 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, 59209653874858713274180299714158372840

Hash 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, 153679601071624610141668476986592179913

Hash 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, 153679601071624610141668476986592179913

Confirm 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> ()  // true

See Also

hash_value_uint128_convert, murmurhash3f, and murmurhash3f_with_seed.

haversine

View source
haversine[r, x1, y1, x2, y2]
haversine(r, x1, y1, x2, y2, hs)

The great circle distance of two points, (x1,y1)(x1, y1) and (x2,y2)(x2, y2), on a sphere of radius rr, using the Haversine formula. The two points are specified by their latitude and longitude in radians.

Parameters

ParameterTypeDescription
x1FloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64]xx coordinate of the 2D point (x1,y1)(`x1`, `y1`). Must be gounded.
y1FloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64]yy coordinate of the 2D point (x1,y1)(`x1`, `y1`). Must be gounded.
x2FloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64]xx coordinate of the 2D point (x2,y2)(`x2`, `y2`). Must be gounded.
y2FloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64]yy coordinate of the 2D point (x2,y2)(`x2`, `y2`). Must be gounded.
rFloatBinary[#64], SignedInteger[#64], UnsignedInteger[#64]rr radius of sphere. Must be grounded.
hsUnsignedInteger[#64], SignedInteger[#64], FloatBinary[#64]Haversine of (x1,y1)(`x1`, `y1`) and (x2,y2)(`x2`, `y2`) on sphere of radius rr.

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.707963267948964

Calculate 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.897244441795649

Hour

View source
Hour[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.

if_then_else

View source
if C then T else F end

Branching on logical condition.

iff

View source
F iff G
F  G

If and only if (boolean equivalence), for boolean (arity 0, true or false) arguments F and G.

implies

View source
F implies G
F  G
G  F

Logical implication, for boolean (arity 0, true or false) arguments F and G.

int

View source
int[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 source
int_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] : error

int_spread_by_even

View source
int_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

ParameterTypeDescription
RRelationSource relation. Must be grounded.
valueIntInteger to be divided among tuples as spread. Must be grounded.
x...TupleA tuple in R.
spreadFloatBinary[#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, 10

Spread 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, 10

Spread 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, 15

See Also

int_spread_by_ratio, FixedDecimal_spread, and spread.

int_spread_by_ratio

View source
int_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

ParameterTypeDescription
RRelationSource relation. Must be grounded.
valueSignedInteger[#64]Integer to be divided among tuples as spread. Must be grounded.
x...TupleA tuple in R.
spreadFloatBinary[#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, 10

Spread 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, 300

See Also

int_spread_by_even, FixedDecimal_spread, and spread.

int128

View source
int128[v]

The 128-bit signed integer value from the integer value v.

int64

View source
int64[v]

The 64-bit signed integer value from the integer value v.

Integer

View source
Integer(x)

Holds if x is an integer (fixed size or arbitrary precision).

Parameters

ParameterTypeDescription
xIntegerAn 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; 0x05

See Also

FixedSizeInteger, BigInteger, SignedInteger, and UnsignedInteger

intersect

View source
intersect[R, S]
R  S

Intersect two n-ary relations R and S

is_Day

View source
is_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 source
is_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 source
is_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 source
is_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 source
is_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 source
is_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 source
is_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 source
is_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 source
is_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 source
is_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 source
json_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 source
last[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
//        5

left_override

View source
left_override[R, S]
R <++ S

The (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.

ExampleValue
2 <++ 32
1.5 <++ 31.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 source
levenshtein[string1, string2]

Calculate the Levenshtein distance between two strings.

Example:

levenshtein["kitten", "sitting"]
3

like_match

View source
like_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> ()  // true

lined_csv

View source
lined_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 source
load_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 source
load_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 type RelName) and the data type as String. For example, the pair (:a, "int") indicates that column :a has type "int". The following data types are supported:
    NameType
    "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 the Int indices indicate the column order, and the column name is provided as a Symbol (of type RelName). This option overrides the default (or existing) header names.
    • :header_row: An Int that 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: An Int that specifies the row from where to start parsing values into relations.
    • :missingstrings: One or multiple String values that should be interpreted as missing values. By default, only empty fields are considered missing.
    • :delim: An ASCII Char that delimits individual fields while parsing. Defaults to ','.
    • :quotechar: An ASCII Char that signals a “quoted” field while parsing. Defaults to '"'.
    • :escapechar: An ASCII Char used to “escape” one or multiple quotechar and other escapechar values within a quoted (e.g., text) field. Defaults to '\\'.
    • :decimalchar: An ASCII Char to be used when parsing float values that separates a decimal value. Defaults to '.'.
    • :groupmark: An ASCII Char denoting the number grouping mark, this allows parsing of numbers that have e.g., thousand separators (like 1,000.00). By default, no group marks are permitted in numbers. If :groupmark and :delim are the same Char, then group marks are only permitted in “quoted” numbers. For instance, if both :groupmark and :delim are ',', 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 source
load_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 source
load_iceberg[URI_string]
load_iceberg[R]

Load one or multiple Apache Iceberg tables from cloud storage.

Parameters

ParameterTypeDescription
URI_stringStringString URI where the data resides.
RRelationConfiguration 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 source
load_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 source
load_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 source
load_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 source
load_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 source
load_parquet[URI_string]
load_parquet[R]

Load one or multiple Parquet files from cloud storage.

Parameters

ParameterTypeDescription
URI_stringStringString URI where the data resides.
RRelationConfiguration 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 source
log[x, y]

Logarithm of y with given base x.

Defined for non-negative x and y.

Example:

log[2, 8] = 3.0

log_card_est

View source
log_card_est[R]

The log base 2 of the cardinality estimate of a given relational abstraction R.

log10

View source
log10[x]

Base 10 logarithm.

Defined for non-negative x.

log10[1000] = 3.0

lowercase

View source
lowercase[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.

lt

View source
lt(x, y)
x < y

lt_eq

View source
lt_eq(x, y)
x  y
x <= y

mae

View source
mae[YHAT, Y]

Mean absolute error (MAE, L1)

max

View source
max[R]
max(R, m)

The maximum value (m) of the last element of all tuples in a relation R.

Parameters

ParameterTypeDescription
RRelationSource relation. Must be grounded.
mNumberThe 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> 6

Find 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.7

Find 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/5

Find 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> 30

See Also

maximum, min, argmax, sum, product, and average.

Max

View source
Max[R]

Please use max[R]. Deprecates in near future

max_k

View source
max_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

ParameterTypeDescription
kSignedInteger[#64]Number of distinct largest values to be calculated for R.
RRelationSource relation. Must be grounded.
mkNumberThe 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, 6

Find 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.7

See Also

min_k, argmin, maximum, min, argmax, sum, product, and average.

maximum

View source
maximum[x, y]

Maximum of two arguments. The arguments should have the same type.

Examples:

maximum[3, 4] = 4
maximum[3.0, 4.0] = 4.0

See Also

max, minimum, and min.

mean

View source
mean[R]
mean(R, m)

The arithmetic mean (m) of the last elements of each tuple in the relation R.

Parameters

ParameterTypeDescription
RRelationSource relation. Must be grounded.
mNumberThe 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.5

Calculate 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/21

Calculate 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.0

Calculate 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.0

See Also

geometric_mean, harmonic_mean, weighted_mean, mode, max, min, sum, and product.

mean_normalization

View source
mean_normalization[R]

Mean normalization: xn=(xnmean[R])/max[R]min[R]x_n = (x_n - {\rm mean}[R]) / {\rm max}[R] - {\rm min}[R]

median

View source
median[R]
median(R, m)

The median value of the last elements of each tuple in the relation R.

Parameters

ParameterTypeDescription
RRelationSource relation. Must be grounded.
mNumberThe 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.35

Determine 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.7

Determine 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.0

metaphone

View source
metaphone[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> rlxn

Here 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 source
Microsecond[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 source
Millisecond[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 source
min[R]
min(R, m)

The minimum value (m) of the last element of all tuples in a relation R.

Parameters

ParameterTypeDescription
RRelationSource relation. Must be grounded.
mNumberThe 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> 3

Find 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/7

Find 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/7

Find 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> 2

See Also

minimum, max, argmax, sum, product, and average.

Min

View source
Min[R]

Please use min[R]. Deprecates in near future

min_k

View source
min_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

ParameterTypeDescription
kSignedInteger[#64]The number of distinct minimum values to be calculated for R.
RRelationSource relation. Must be grounded.
mkNumberThe 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, 3

Determine 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.6

See Also

max_k, argmin, minimum, min, argmax, sum, product, and average.

min_max_normalization

View source
min_max_normalization[R]

Min-Max normalization: xn=(xnmin[R])/max[R]min[R]x_n = (x_n - {\rm min}[R]) / {\rm max}[R] - {\rm min}[R].

Also known as min-max scaling or rescaling.

minimum

View source
minimum[x, y]

Minimum of two arguments. The arguments should have the same type.

Examples:

minimum[3, 4] = 3
minimum[3.0, 4.0] = 3.0

Minute

View source
Minute[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 source
missing

Singleton missing value.

Examples:

missing[] = missing
equal( (x : missing(x)) , {missing} )

Missing

View source
Missing(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 source
mode[R]
mode(R, md)

Find the most common value in the last element of all tuples in a relation R.

Parameters

ParameterTypeDescription
RAnySource relation. Must be grounded.
mdAnyThe 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 source
ic model_is_function

An integrity constraint ensuring that rel:catalog:model has a functional dependency from the name to the actual value.

modulo

View source
modulo[x, y]
modulo(x, y, m)

Remainder after floored division.

Parameters

ParameterTypeDescription
xNumberDividend. Must be grounded.
yNumberDivisor. Must be grounded.
mNumberRemainder.

Not all numeric values can be mixed with each other. The following combinations work:

xym
NumberSame as xSame as x
SignedInteger, UnsignedIntegerSignedInteger, UnsignedIntegerType of y. Bit size is the larger of the bit sizes of x and y.
SignedInteger[#64], FloatBinary[#64]NumberType of x.
NumberSignedInteger[#64], FloatBinary[#64]Type of y.
FloatBinarySignedInteger[#64]Type of x.
SignedInteger[#64]FloatBinaryType of y.
RationalSignedInteger[#64]Rational[n] where n is the greater of the number of bits in x and y.
SignedInteger[#64]RationalRational[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> 2

Compute remainder for two integers using full expression:

def output(m) = modulo(8, -3, m)
//output> -1

Compute remainder for rational and integer:

def output = modulo[rational[64, 8, 3], 2]
//output> 2/3

Confirm that modulo is empty when y = 0:

def output = empty(modulo[3, 0])
//output> ()  // true

Month

View source
Month[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.

mse

View source
mse[YHAT, Y]

Mean squared error (MSE, L2)

multiply

View source
multiply[x, y]
multiply(x, y, p)
x * y

Multiplication of two numbers.

Parameters

ParameterTypeDescription
xNumberFirst factor. Must be grounded.
yNumberSecond factor. Must be grounded.
pNumberProduct x * y.

Not all numeric values can be mixed with each other. The following combinations work:

xyp
NumberSame as xSame as x
Rational, FixedDecimalSignedInteger, UnsignedIntegerSame as x
SignedInteger, UnsignedIntegerRational, FixedDecimalSame as y
SignedInteger[#64]SignedInteger[#128]SignedInteger[#128]
SignedInteger[#128]SignedInteger[#64]SignedInteger[#128]
NumberFloatBinary[#64]FloatBinary[#64]
FloatBinary[#64]NumberFloatBinary[#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> 48

Multiply one float by another using multiply:

def output = multiply[8.4, 2.1]
//output> 17.64

Multiply a rational by an integer using full expression:

def output(x) = multiply(rational[64, 8, 3], 2, x)
//output> 16/3

See Also

add, subtract, and divide.

murmurhash3f

View source
murmurhash3f[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 source
murmurhash3f_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:

https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash3.cpp (opens in a new tab)

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] = 0x9116cd3f0a651c49f1674100935b29bf

Nanosecond

View source
Nanosecond[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 source
nanoseconds_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).

natural_exp

View source
natural_exp[x]

Exponentiation with the base of the natural log, e.

natural_log

View source
natural_log[x]

Natural logarithm (ln) (base e).

Defined for non-negative x.

neq

View source
neq(x, y)
x  y
x != y

Examples:

  • 1 != 2 is true
  • 1 != 1.0 is true
  • 1 != "a" is true

num_bytes

View source
num_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["中文例子"] = 12

num_chars

View source
num_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["中文例子"] = 4

Number

View source
Number(x)

Holds if x is a number (for example, Int ,Float, or their fixed-width versions).

See Also

int and float.

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 source
numerator[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]  =  5

pack

View source
pack(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 source
parse_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-12

For details on the format parameter, see the Julia documentation for Dates.DateFormat (opens in a new tab).

parse_datetime

View source
parse_datetime[date_string, format]
parse_datetime(date_string, format, date)

Parses datetime information (date_string) given a date-time format (format).

Parameters

ParameterTypeDescription
date_stringStringA string with date and time information formatted according to format. Must be grounded.
formatStringA valid date-time format. Must be grounded.
dateDateTimeA 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

ParameterExampleDescription
y2024Matches year.
m1, 01Matches 1 or 2-digit months.
d1, 01Matches 1 or 2-digit days.
H00Matches hours (24-hour clock).
I00For outputting hours with 12-hour clock.
M00Matches minutes.
S00Matches seconds.
s.500Matches milliseconds.
eMon, TuesMatches abbreviated days of the week.
EMondayMatches full name days of the week.
pAMMatches AM/PM (case-insensitive).
yyyymmdd19960101Matches fixed-width year, month, and day.
z+04:00, +0400, UTC+4Matches a numeric UTC offset.
ZAsia/Dubai, UTCMatches names of time zones from the TZ database.
uJanMatches abbreviated months according to the _locale_keyword.
UJanuaryMatches 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.000Z

Parse 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.003Z

Parse 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.000Z

where 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 source
parse_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 source
parse_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 source
parse_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 source
parse_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 source
parse_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 source
parse_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 source
parse_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 source
parse_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 source
parse_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"] = 0x22b4a8a1e5484eeb927060426d66a48e

Pattern

View source
Pattern(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 source
pattern_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> ()  // true

percentile

View source
percentile[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.6

percentile_nearest

View source
percentile_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> 16

period_add

View source
period_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> 7

period_day_to_int

View source
period_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 source
period_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> ()  // true

period_min

View source
period_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> ()  // true

pi_float64

View source
pi_float64

The constant pi.

Example:

cos[pi_float64] = -1.0

pivot

View source
pivot[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

ParameterTypeDescription
TRelationSource relation. Must be grounded.
tuple_positionIntThe position of the element value within T.
valueAnyAn 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, engineering

If 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, 6

pop_standard_deviation

View source
pop_standard_deviation[R]
pop_stddev[R]

Population standard deviation

pop_variance

View source
pop_variance[R]

Population variance

pop_zscore_normalization

View source
pop_zscore_normalization[R]

Z-score normalization (population) of (the last argument of) the relation R.

power

View source
power[b, n]
power(b, n, e)
b ^ n

Exponentiation of b to the power of n.

Parameters

ParameterTypeDescription
bNumberBase. Must be grounded.
nNumberExponent. Must be grounded.
eNumberExponentiation b ^ n.

Not all numeric values can be mixed with each other. The following combinations are valid:

bne
NumberSignedInteger[#64]Same as b
SignedInteger[#64], FloatBinary[#64]FloatBinary[#64]FloatBinary[#64]
BigIntegerBigIntegerBigInteger

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, 25

One can also mix integer and floating-point numbers:

def output = power(3.0, 2, 9.0)
//output> ()  // true

However, the exponent needs to have an integer value when the base is negative:

def output = (-10)^-4.0
// output> 0.0001

prefix_join

View source
prefix_join[R, S]
R <: S

The 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.

ExampleNormalized
n <: edgex, y: edge(x, y) and x = n
female <: parentx, y: female(x) and parent(x, y)
t <: playersx, p: players(x, p) and t = x
t.players <: agep, v: players(t, p) and age(p, v)
intern <: salaryp, v: intern(p) and salary(p, v)

The restriction operator can also be used to select subsets of JSON-like relations:

  • :a <: json where json is {"a": {"b": 1, "c": 2}, "d": 3} has value {"a": {"b": 1, "c": 2}}

  • (:[], _, :a) <: json where json is [ {"a": 1, "b": 2}, {"a": 3, "b": 4} ] has value [ {"a": 1}, {"a": 3} ].

product

View source
product[R]
product(R, p)

The product (p) of the last element of all tuples in a relation R.

Parameters

ParameterTypeDescription
RRelationA relation whose tuples contain numeric data types. Must be grounded.
pNumberThe 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> 20

Calculate 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/35

Calculate 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.375

Calculate 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/7

See Also

multiply, min, argmax, sum, and average.

proper_subset

View source
proper_subset(R, S)
R  S

R 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.

proper_superset

View source
proper_superset(R, S)
R  S

Inverse of proper_subset. See proper_subset.

rad2deg

View source
rad2deg[r]
rad2deg(r, d)

Convert radians to degrees.

Parameters

ParameterTypeDescription
rFloat, Intd in radians. Must be grounded.
dFloatr in degrees.

Examples

Convert -π/2 to degrees:

def output = rad2deg[-pi_float64/2]
//output> -90.0

Convert π to degrees using full expression:

def output(d) = rad2deg(pi_float64, d)
//output> 180.0

random_mersenne_twister

View source
random_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 source
random_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.14708645730224323

Generating 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 source
random_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> 0xbf025a77543cc31d

Generating 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 source
random_uint128

Random 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 source
random_uint64

Random 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 source
range[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

ParameterTypeDescription
startInt[b], UInt[b], FloatStarting point for range (inclusive). Must be grounded.
stopsame as startEnding point for range (inclusive). Must be grounded.
stepsame as startStep size. Positive integer. Must be grounded.
xsame as startResult 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
//        10

Generate 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.0

rational

View source
rational[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 source
Rational(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/7

rational_convert

View source
rational_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 source
RationalNumber(x)

Holds if x is a rational number.

Parameters

ParameterTypeDescription
xRationalNumberAn 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//7

See Also

FixedSizeRational, SignedRational

regex_compile

View source
regex_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> ()  // true

regex_match

View source
regex_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 source
regex_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 source
bound rel:catalog:model

Declare 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 source
bound rel:catalog:model_creation_time

Declare 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 source
bound rel:catalog:model_update_time

Declare 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 source
rel: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[...], where m is the current partition and n the 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 :path prefix.

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 source
rel: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 source
rel: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 source
RelName(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 source
relname_string[my_relname]
relname_string(my_relname, my_string)

Convert RelName (my_relname) data into String data (my_string).

Parameters

ParameterTypeDescription
my_relnameRelNameA valid RelName.
my_stringStringA 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:

  1. Verify that a RelName and string match. relname_string(relation_name, string) evaluates to true if relation_name matches string. If relation_name does not match string, relname_string(relation_name, string) evaluates to false (the empty relation, {}).
  2. 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

string.

remainder

View source
remainder[x, y]
remainder(x, y, r)
x % y

Remainder from truncated division.

Parameters

ParameterTypeDescription
xNumberDividend. Must be grounded.
yNumberDivisor. Must be grounded.
rNumberRemainder.

Not all numeric values can be mixed with each other. The following combinations work:

xyr
NumberSame as x.Same as x.
SignedInteger, UnsignedIntegerSignedInteger, UnsignedIntegerSignedInteger[#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, FixedDecimalSignedInteger[#64]Same as x.
SignedInteger[#64]FloatBinary, FixedDecimalSame as y.
RationalSignedInteger[#64]Rational[n], where n is the greater of the number of bits in the types of x and y.
SignedInteger[#64]RationalRational[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> 2

Compute remainder of integer divided by integer using remainder:

def output = remainder[-8, 3]
//output> -2

Compute remainder of integer divided by negative integer using full expression:

def output(r) = remainder(8, -3, r)
//output> 2

Compute remainder of rational divided by negative integer:

def output = remainder[rational[64, 8, 3], -2]
//output> 2/3

Confirm that remainder is false (empty) when y is 0:

def output = empty(remainder[6, 0])
//output> ()  // true

reverse_sort

View source
reverse_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 source
right_override[R, S]
R ++> S

Right 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:

ExampleValue
2 ++> 33
(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)

rmse

View source
rmse[YHAT, Y]

Root mean square error (RMSE)

round

View source
round[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

ParameterTypeDescription
modeRelNameMode for rounding. Must be grounded.
xNumberNumber to be rounded. Must be grounded.
rNumberResult of rounding x. Same type as x.

Available Modes

modeDescription
:ROUND_UPRound up to the nearest integer.
:ROUND_DOWNRound down to the nearest integer.
:ROUND_NEARESTRound to the nearest integer, with ties (fractional values of 0.5) being rounded to the nearest even integer.
:ROUND_NEAREST_TIES_AWAYRound to the nearest integer, with ties rounded away from zero.
:ROUND_NEAREST_TIES_UPRound to the nearest integer, with ties rounded toward positive infinity.
:ROUND_TO_ZERORound toward zero to the nearest integer.

Examples

Round nearest float:

def output = round[:ROUND_NEAREST, -8.555]
//output> 9.0

Round up rational:

def output = round[:ROUND_UP, rational[64, 8, 3]]
//output> 3/1

Round down float using full expression:

def output(r) = round(:ROUND_DOWN, 8.4, r)
//output> 8.0

Round 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.0

See Also

floor, floor_to_int, ceil, trunc, and trunc_to_int.

round

View source
round[x]
round(x, r)

Round x to the nearest integer. The rounded number is of the same data type as x.

Parameters

ParameterTypeDescription
xNumberNumber to be rounded. Must be grounded.
rNumberResult 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.0

Rounding a fractional:

def output = round[rational[64, 7, 3]]
//output> 2/1

sample_standard_deviation

View source
sample_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_variance

View source
sample_variance[R]

Sample variance

sample_zscore_normalization

View source
sample_zscore_normalization[R]

Z-score normalization (sample) of (the last argument of) the relation R.

Often simply referred to as ‘standardization’.

Second

View source
Second[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 source
second[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"

sign

View source
sign[x]

The sign of x: either 0, -1, or 1.

SignedInt

View source
SignedInt(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 source
SignedInteger(#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 source
SignedRational(#nbits, x)

Holds if x is an nbits rational.

Parameters

ParameterTypeDescription
#nbits#(Int)A specialized integer (must be a valid bit size).
xRationalA 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/7

See Also

Rational and Number.

sin

View source
sin[x]
sin(x, s)

Sine of x, where x is an angle given in radians.

Parameters

ParameterTypeDescription
xSignedInteger[#64], FloatBinary[#64]Angle in radians. Must be grounded.
sFloatBinary[#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> 1

Calculate the sine of 5π/6:

def output = sin[5 * pi_float64/6]
//output> 0.49999999999999994

See Also

asin, sinh, asinh, cos, acos, cosh, acosh, tan, atan, tanh, and atanh.

sinh

View source
sinh[x]
sinh(x, sh)

Hyperbolic sine. sh is the hyperbolic sine of x.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Hyperbolic angle. Must be grounded.
shFloatBinary[#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.3161232732465

Calculate the hyperbolic sine of -1 using full expression:

def output(x) = sinh(-1, x)
//output> -1.1752011936438014

Confirm that 548.3161232732465 is the hyperbolic sine of 7:

def output = sinh(7, 548.3161232732465)
//output> ()  // true

See Also

sin, cos, asin, acos, asinh, acosh, cosh, and haversine.

sort

View source
sort(R, index, x...)

Enumerate the tuples in a relation.

Parameters

ParameterTypeDescription
RRelationRelation to be enumerated. Must be grounded.
indexIntThe new enumeration index starting at 1.
x...TuplesA 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

enumerate.

soundex

View source
soundex[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> c623

Here 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 source
spread[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

ParameterTypeDescription
modeRelName:even or :ratio.
RRelationSource relation. Must be grounded.
valueInt, FixedDecimalInteger or decimal to be divided among tuples as spread. Must be grounded.
x...TupleA tuple in R.
spreadFloatSpread 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.333

Spread 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, 10

Spread 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.304

See Also

int_spread_by_ratio, int_spread_by_even, and FixedDecimal_spread.

sqrt

View source
sqrt[x]

The non-negative square root of x.

Defined for non-negative x.

squared

View source
squared[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 source
squared_deviation[R]

Squared deviation: squared deviation from the mean of (the last argument of) the relation R.

starts_with

View source
starts_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")   // false

string

View source
string[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 source
String(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 source
string_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

ParameterTypeDescription
separatorChar or StringCharacter or String used to separate adjacent strings. Must be grounded.
RRelationA binary relation containing tuples of the form (Int, String). Must be grounded.
new_stringStringResulting 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:

  1. The integer index represents the order of the strings to be joined, and serves as the sort key for concatenation.
  2. The string text represents 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 source
string_length[string]

DEPRECATED

This function is deprecated. Use num_chars[string] or num_bytes[string], depending on your need.

Example:

string_length["foo"] = 3

string_replace

View source
string_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 source
string_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 source
string_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 source
string_trim[s]

To remove leading and tailing white spaces in given string s.

Example:

string_trim["  Good Day!!!  "] = "Good Day!!!"

subset

View source
subset(R, S)
R  S

R 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 of R. If R also contains facts of a different arity, then the implication remains true, even when R ⊈ S.

  • subset(R, S), defined as forall(xs... where R(xs...) : S(xs...)), is true only if there exists no fact in R, of any arity, that is not also in S.

substring

View source
substring[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

ParameterTypeDescription
mystringStringSource text. Must be grounded.
iSignedInteger, UnsignedIntegerThe position where substring begins. Must be grounded.
jSignedInteger, UnsignedIntegerThe position where substring ends. Must be grounded.
substringStringA 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> bc

Get 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> abc

Get the substring containing the characters starting at index 2 and with j out of bounds:

def output = substring["abcd", 2, 7]
//output> bcd

See Also

substring_bytes, starts_with, ends_with, and string_replace.

substring_bytes

View source
substring_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 source
subtract[x, y]
subtract(x, y, d)
x - y

Subtraction of one number from another. Subtraction of a date, datetimes, and periods.

Parameters

Numeric Data

ParameterTypeDescription
xNumberSubtrahend.
yNumberMinuend.
dNumberDifference x - y.

Not all numeric values can be mixed with each other. The following combinations work:

xyd
NumberSame as xSame as x
SignedInteger[#64]SignedInteger[#128], FloatBinary[#64], FixedDecimal, RationalSame as y
SignedInteger[#128], FloatBinary[#64], FixedDecimal, RationalSignedInteger[#64]Same as x

Two of the three arguments need to be grounded. Valid grounding combinations are as follows:

  • x and y.
  • x and d.
  • y and d.

Time Data

ParameterTypeDescription
xDate, DateTime, date period, time periodMinuend.
yDate, DateTime, date period, time periodSubtrahend.
dDate, DateTime, date period, time periodDifference x - y.

The following combinations work:

xyd
date period, time periodSame date period, time period as xSame Date period, time period as x
DateTimedate period, time periodDateTime
DateTimeDateTimeTime period in Millisecond
Datedate periodDate
DateDatedate period in Day

Two of the three arguments need to be grounded. Valid grounding combinations are as follows:

  • x and y.
  • x and d.
  • y and d.

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> 3

Subtract a float from an integer using subtract:

def output = subtract[7, 5.25]
//output> 1.75

Subtract two floats using full expression:

def output(x) = subtract(8.5, 5.25, x)
//output> 3.25

Subtract a rational from an integer:

def output = x - rational[16, 2, 3]
//output> 4/3

Calculate integer subtracted by providing x and d:

def output(y) = subtract(2899, y, 2865)
//output> 34

Subtraction 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> 136800000

Subtract weeks from a date:

def output = 2024-01-10 - ^Week[2]
//output> 2023-12-27

Subtract 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> -11

Calculate date subtracted by providing date and resulting period:

def output(y) = subtract(2022-10-01, y, ^Day[10])
//output> 2022-09-21

Subtract 2 seconds from 6 seconds:

def output = ^Second[6] - ^Second[2]
//output> 4

See Also

add, divide, and multiply.

suffix_join

View source
suffix_join[R, S]
R :> S

The 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.

ExampleNormalized
edge :> nx, y: edge(x, y) and y = n
parent :> femalex, y: parent(x, y) and female(y)
account_balance :> positivex, 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 :> even where json is [ {"a": 1, "b": 2}, {"a": 3, "b": 4, "c": 6} ] has value [ {"b": 2}, {"b": 4, "c": 6} ]

  • json :> (:b, even) where json is [ {"a": 1, "b": 2}, {"a": 3, "b": 4, "c": 6} ] has value [ {"b": 2}, {"b": 4} ]

sum

View source
sum[R]
sum(R, s)
Σ[R]
Σ(R, s)

Sum of the last element of all tuples in a relation.

Parameters

ParameterTypeDescription
RRelationSource relation. Must be grounded.
sNumberThe 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> 62

Calculate 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
          6

Calculate 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.8

Calculate 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", 260

See Also

add, sum_int, min, argmax, sum, and average.

sum_int

View source
sum_int[R]
sum_int(R, si)

Sum over the last elements in the tuples of R, which must be integers.

Parameters

ParameterTypeDescription
RRelationA grounded relation. The last element of every tuple must be an integer.
siSignedInteger[#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> 88

Evaluate the sum of a relation with various tuple lengths:

def salary = {("John", 10) ; ("Mary", "Smith", 20); }
def output = sum_int[salary]
//output> 30

The sum over an empty relation is zero:

def output = sum_int[{}]
//output> 0

See Also

sum, add, min, max, product, and average.

superset

View source
superset(R, S)
R  S

Inverse of subset. See subset.

tan

View source
tan[x]
tan(x, t)

Tangent. t is the tangent of x, where x is in radians.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Angle in radians. Must be grounded.
tFloatBinary[#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.9999999999999999

Convert degrees to radians and calculate tangent using full expression:

def x = deg2rad[90]
def output(t) = tan(x, t)
//output> 16331239353195370.0

Confirm that 0.9999999999999999 is the tangent of π/4:

def output = tan(pi_float64/4, 0.9999999999999999)
//output> ()  // true

See Also

atan, atan2, cot, acot, tanh, and atanh.

tanh

View source
tanh[x]
tanh(x, th)

Hyperbolic tangent. th is the hyperbolic tangent of x.

Parameters

ParameterTypeDescription
xFloatBinary[#64], SignedInteger[#64]Hyperbolic angle. Must be grounded.
thFloatBinary[#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.9999983369439447

Calculate the hyperbolic tangent of -1 using full expression:

def output(x) = tanh(-1, x)
//output> -0.7615941559557649

Confirm that 0.9999983369439447 is the hyperbolic tangent of 7:

def output = tanh(7, 0.9999983369439447)
//output> ()  // true

See Also

tan, atan, atan2, cot, acot, and atanh.

top

View source
top[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

ParameterTypeDescription
RRelationSource relation. Must be grounded.
kIntNumber of tuples to enumerate from the top of R. Must be grounded.
indexIntThe new enumaration index starting at 1.
x...TupleA 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, 3

See Also

bottom, enumerate, sort, and reverse_sort.

total

View source
total(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 source
transpose[R]

Transpose a binary relation (swap the two arguments).

Example:

def output = transpose[{(1, 2); (3, 4)}]
//output> (2, 1)
//        (4, 3)

trunc

View source
trunc[x]
trunc(x, t)

Round toward zero to the nearest integer.

Parameters

ParameterTypeDescription
xNumberNumber to be rounded toward zero. Must be grounded.
tIntTruncated 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.0

Truncate negative float using full expression:

def output(t) = trunc(-4.9, t)
//output> -4.0

Truncate rational:

def output = trunc[rational[64, 27, 5]]
//output> 5/1

See Also

floor, floor_to_int, ceil, trunc_to_int, and round.

trunc_divide

View source
trunc_divide[x, y]
trunc_divide(x, y, q)
x ÷ y

Division of two numbers, rounding the result to the nearest integer toward zero.

Parameters

ParameterTypeDescription
xNumberNumerator. Must be grounded.
yNumberDenominator. Must be grounded.
qNumberTruncated quotient x / y.

Not all numeric values can be mixed with each other. The following combinations work:

xyq
SignedInteger[#64]SignedInteger[#64]SignedIneger[#64]
SignedInteger[#64]FloatBinary[#64]FloatBinary[#64]
FloatBinary[#64]SignedInteger[#64], FloatBinary[#64]FloatBinary[#64]
RationalSignedInteger[#64]SignedInteger[#64]
FixedDecimalSignedInteger[#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> 2

Use truncated division to divide an integer by another integer using trunc_divide:

def output = trunc_divide[5, 2]
//output> 2

Use truncated division to divide a negative integer by a positive integer:

def output = trunc_divide[-5, 2]
//output> -2

Use truncated division to divide a decimal by an integer using full expression:

def output(x) = trunc_divide(5.1, 2, x)
//output> 2.0

Use truncated division to divide a rational by an integer using full expression:

def output(t) = trunc_divide(rational[64, 26, 3], 2, t)
//output> 4

trunc_to_int

View source
trunc_to_int[x]
trunc_to_int(x, t)

Convert float to integer, truncating.

Parameters

ParameterTypeDescription
xFloatNumber to be rounded down. Must be grounded.
tIntTruncated 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> 3

Convert negative float to integer, truncating, using full expression. Note that rounding goes toward zero.

def output = trunc_to_int[-3.1]
//output> -3

Confirm that trunc_to_int returns false (empty) when x is an integer:

def output = trunc_to_int[3]
//output>    // false

See Also

floor, floor_to_int, ceil, trunc, and round.

uint

View source
uint[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

View source
uint128[v]

The 128-bit unsigned integer value from the integer value v.

uint128_hash_value_convert

View source
uint128_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 source
uint128_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]] = 1

uint64

View source
uint64[v]

The 64-bit unsigned integer value from the integer value v.

union

View source
union[R, S]
R  S

Union two n-ary relations R and S

unit_normalization

View source
unit_normalization[R]

Unit vector normalization: xn=xn/(Σ(x2))0.5x_n = x_n / ( Σ (x^2) ) ^ {0.5}

unix_epoch

View source
unix_epoch

The beginning of the UNIX Epoch, midnight on 1 January 1970 (UTC).

unpack

View source
unpack(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 source
UnsignedInt(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 source
UnsignedInteger(#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 source
uppercase[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 source
uuid_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 source
Week[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 source
weighted_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

ParameterTypeDescription
RRelationA relation whose last elements contain numeric data types and whose first elements match W. Must be grounded.
WRelationWeight for weighted mean. A relation whose last elements contain numeric data types and whose first elements match R. Must be grounded.
wmNumberThe 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.3

Calculate 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.3

Calculate 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.3

See Also

geometric_mean, harmonic_mean, mean, mode, max, min, sum, and product.

xor

View source
F xor G
F  G
F  G

Exclusive OR, for boolean (arity 0, true or false) arguments F and G.

Year

View source
Year[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 source
zip[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)

Σ

View source
Σ[R]
Σ(R, s)

Sum of the last element of all tuples in a relation. Alias for sum.

Module: rel:base

View source

FilePos

View source
FilePos(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

ParameterTypeDescription
xFilePosFilePos variable.
yIntegerThe 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 source
FixedDecimal(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 Float

See Also

decimal and parse_decimal.

UUID

View source
UUID(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

ParameterTypeDescription
xUUIDUUID variable.
yUInt128The 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> 32314330545176713121947364484890423080

The 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 source
uuid_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 source
SHA1(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

ParameterTypeDescription
xSHA1SHA1 variable.
aUInt128The first 128 bits of the 160 bits SHA-1 value.
bUInt32The 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 source
sha1_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 source
Date(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

ParameterTypeDescription
dDateDate variable.
nIntegerThe 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-15

Construct a date from its parts (year, month, day).

^Date[2012, 5, 15]
//output> 2012-05-15

Subtract two date literals. The result is of type Day.

def output = 2012-06-15 - 2012-05-15
//output> 31

DateTime

View source
DateTime(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

ParameterTypeDescription
dtDateTimeDateTime variable.
nIntegerThe 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.000Z

Construct 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.000Z

Subtract two datetime literals. The result is of type Millisecond.

def output = 2012-05-15T00:00:00Z - 2012-05-14T00:00:00Z
//output> 86400000

Year

View source
Year(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

ParameterTypeDescription
pYearA period representing n years.
nIntegerThe 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.000Z

Add two Year periods together.

def output = ^Year[10] + ^Year[2]
//output> 12

Month

View source
Month(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

ParameterTypeDescription
pMonthA period representing n months.
nIntegerThe 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.000Z

Add two Month periods together.

def output = ^Month[10] + ^Month[2]
//output> 12

Week

View source
Week(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

ParameterTypeDescription
pWeekA period representing n weeks.
nIntegerThe 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.000Z

Add two Week periods together.

def output = ^Week[10] + ^Week[2]
//output> 12

Day

View source
Day(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

ParameterTypeDescription
pDayA period representing n days.
nIntegerThe 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.000Z

Add two Day periods together.

def output = ^Day[10] + ^Day[2]
//output> 12

Hour

View source
Hour(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

ParameterTypeDescription
pHourA period representing n hours.
nIntegerThe 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.000Z

Add two Hour periods together.

def output = ^Hour[10] + ^Hour[2]
//output> 12

Minute

View source
Minute(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

ParameterTypeDescription
pMinuteA period representing n minutes.
nIntegerThe 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.000Z

Add two Minute periods together.

def output = ^Minute[10] + ^Minute[2]
//output> 12

Second

View source
Second(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

ParameterTypeDescription
pSecondA period representing n seconds.
nIntegerThe 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.000Z

Add two Second periods together.

def output = ^Second[10] + ^Second[2]
//output> 12

Millisecond

View source
Millisecond(p)
^Millisecond(n, p)

A period that spans n milliseconds. The period is given in units of Millisecond (10310^{-3} 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

ParameterTypeDescription
pMillisecondA period representing n milliseconds.
nIntegerThe 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.000Z

Add two Millisecond periods together.

def output = ^Millisecond[10] + ^Millisecond[2]
//output> 12

Microsecond

View source
Microsecond(p)
^Microsecond(n, p)

A period that spans n microseconds. The period is given in units of Microsecond (10610^{-6} 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

ParameterTypeDescription
pMicrosecondA period representing n microseconds.
nIntegerThe 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.000Z

Add two Microsecond periods together.

def output = ^Microsecond[10] + ^Microsecond[2]
//output> 12

Nanosecond

View source
Nanosecond(p)
^Nanosecond(n, p)

A period that spans n nanoseconds. The period is given in units of Nanosecond (10910^{-9} 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

ParameterTypeDescription
pNanosecondA period representing n nanoseconds.
nIntegerThe 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.000Z

Add two Nanosecond periods together.

def output = ^Nanosecond[10] + ^Nanosecond[2]
//output> 12

Module: rel:bignum

View source

BigInteger

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)):

Was this doc helpful?