Skip to content
This site is for a previous version of RelationalAI.


Constants in Rel are semantically equivalent to unary singleton relations (arity 1, cardinality 1). In Rel, the value of every expression is a relation, and this includes constant expressions. For example, the value of the constant 1 is {(1)}.

Note that true and false (see Boolean Constant Relations) are relations of arity 0.

Integer Constants

Examples: 1, 2, and 3.

Floating-Point Constants

Expr := [0-9]+ "." [0-9]* exponent?
      | [0-9]+ exponent
      | "." [0-9]+ exponent?
decimalDigit  := [0-9]
decimalDigits := decimalDigit+
exponent      := ('e' | 'E') ('+' | '-')? decimalDigits


  • 0.0.
  • 3.14.
  • 1.5e4.
  • 1e10.
  • 5e-4.
  • 5e+4.
  • .5e4.

Character Constants

Character constants are enclosed by single quotes. The characters are Unicode characters.

Examples: 'c' and '文'.

String Constants

String constants are constant sequences of characters.

As described in Rel Data Types, the number of characters in a string is computed by num_chars. The characters are indexed from 1, and can be accessed by char.

For example, num_chars["中文例子"] = 4 and char["中文例子", 2] = '文'.

A string constant can be written in one of three different forms, described below.

Strings in Single Double Quotes

A string constant can be enclosed in double quotes: for example, "a string".

The backslash \ is an escape character which can be used to specify characters that would normally be illegal in a string, or difficult to input or see. The most frequently used cases are listed below:

  • The sequence \" represents a double quote character.
  • The sequence \n represents a newline.
  • The sequence \t represents a tab character.
  • The sequence \\ represents a single backslash character.
  • The sequence \% represents the character %, when it is not to be interpreted as beginning string interpolation.

In general, the conventions are as in Julia. Note that unlike in some other languages, an unrecognized escape sequence — such as a backslash followed by a space — is illegal and will cause the compiler to report an error.


def quote = "\""
def output = i, c : char[quote, i, c]

quote will have length 1, and the output will be (1, ").

Strings in Triple Double Quotes

A string constant can also be enclosed in triple double quotes: for example, """a string """. This form of a string constant can span a number of lines:

// read query
"""A multi-line

The example shows that there is no need to escape a double quote inside a triple-quoted string, unless the double quote is followed by at least two unescaped double quotes. So, for instance, the string """" """ contains a quote followed by a space, but to obtain a space followed by a quote in a triple-quoted string you must write """ \"""".

For convenience, a newline that is written immediately after the opening """ will be ignored. Furthermore, if the contents are indented, then the indentation will be ignored. So, the example above could have also been written as:

   A multiline

The exact rules are very similar to those found in Triple-Quoted String Literals (opens in a new tab) of the language Julia (opens in a new tab). There are two differences:

  • An escape character (\) is not allowed at the end of a line.
  • Rel strips away leading tabs or leading spaces, but not both.

Raw Strings

A raw string begins with the identifier raw, immediately followed by N double quotes, where N must be an odd number. The raw string extends until the nearest occurrence of N double quotes:

// read query
The backslash \ and percent sign % usually have special meanings.

Everything between the opening quotes and the closing quotes is just uninterpreted text.


Neither the backslash \ nor the percent sign % have any special meaning in a raw string.

Moreover, indentation and any new newline \n are not ignored, but are included in the string. Most notably, a newline immediately after the opening sequence such as raw" is included in the string, in contrast to what happens in “standard” multiline strings. In the following examples, the two string literals stored in s and r are equivalent:

// read query
def s = "\n123\n"
def r = raw"
def output = r, s

With the raw strings syntax, it is not possible to create a string that begins or ends with a double quote ".

In the example below, the first quote of the contents is preceded by a newline, and the last quote of the contents is followed by a newline:

// read query
"A string."

The following examples are all invalid raw string literals:

  • raw""".
  • raw"" ".
  • raw" "".
  • raw"\"".

Standard string syntax and the sequence \" must be used to create a string value starting or ending with a double quote. For example, "\"".

Here are a few more examples of strings that feature the raw syntax and their equivalents written with the standard string syntax:

  • raw"\" is equivalent to "\\".
  • raw""" " """ is equivalent to " \" ".
  • raw"ab%c" is equivalent to "ab\%c".

The ability to use an arbitrary odd number of quotes makes it relatively easy to convert a complicated text into a single string. For instance, the example below is equivalent to a single string, whose contents — without the surrounding quotes — is shown in the output:

// read query
"""A multi-line

Other interesting points about raw strings:

  • The identifier raw is just a normal identifier, and can be used as, say, the name of a relation. It has special meaning only when immediately followed by a double quote.
  • The only way to write an empty raw string is raw"". While the triple-quoted string """""" is empty, raw"""""" will cause the compiler to raise an error.
  • Raw strings are often convenient, but since their contents are taken literally, raw strings do not support string interpolation.

String Interpolation

Rel allows a string to be interpolated into another string, as long as the latter is not a raw string and does not occur in the head of a definition. String interpolation is introduced by an unescaped percent sign, %.

For example, "a%("b")c" is equivalent to "abc".

A more interesting example: If the value of variable v is the string "inner", then "This is the %(v) string" is equivalent to "This is the inner string".

In the case of a simple identifier, the parentheses may be omitted.

The interpolated string can be represented by an arbitrary Rel expression of arity 1, which makes this feature quite powerful. For example:

// read query
def R = (1, "one"); (2, "two"); (3, "three")
def output = """The number %(R[2])."""

In the context of interpolation Rel will perform conversions from other types to strings. For instance:

// read query
def add_these = 1, 2; 10, 5
def output = "For example: %x + %y = %z"
              from x, y, z where add_these(x, y) and z = x + y

Interpolation can be nested:

// read query
def from_id = ("user_1", "Alice"); ("user_2", "Bob")
def nums = 1; 2; 3
def output = "Hello %(from_id["user_%nums"]) and bye"

Date Constants

Expr := [0-9][0-9][0-9][0-9] "-" [0-9][0-9] "-" [0-9][0-9]

Constants of type Date are written in the ISO 8601 extended format.

Examples: 2021-01-01 and 2100-04-03.

If a date does not exist (for example, 2021-02-30 or 2020-25-01) then a warning is reported and the value of the constant is the unary empty relation.

DateTime Constants

Expr := Date "T" Time Timezone
Date := [0-9][0-9][0-9][0-9] "-" [0-9][0-9] "-" [0-9][0-9]
Time := [0-9][0-9] ":" [0-9][0-9] ":" [0-9][0-9]
Timezone := "Z"
         | "+" [0-9][0-9] ":" [0-9][0-9]
         | "-" [0-9][0-9] ":" [0-9][0-9]

Constants of type DateTime use the ISO 8601 extended format. A time zone is required.

Example: 2021-01-01T21:00:00+00:00.

If a DateTime is not valid then a warning is reported and the value of the constant is the unary empty relation.

Next: Relational Abstractions

Was this doc helpful?