The Basics
This section covers the fundamentals of Regle Query Language (ReQL).
Feature
Features in ReQL is created via a LET statement.
LET <feature_name> = <expression>;
Features is what other programming languages typically refer to as variables.
Feature name must be capitalized in tw.
Features in tw is typed but you do not need type annotation except when dealing with functions that can return multiple types (see Type System to learn more)
LET StringLiteral = "Hello World";
LET RandomNumber = random();
Features are immutable once created. Feature names cannot be reused.
Function
Function names in ReQL is always camelcase and a function call is identified by round brackets - ex. random().
ReQL does not support user defined functions. Instead, ReQL provides a rich set of built-in functions (see Built-in Functions) to manipulate features.
Function calls in ReQL serve 2 broad purposes
1) Data transformation
- ex.
ipToCountrytakes an IP and returns the geo-located country string
2) Interacting with External Services
- ex.
getCountreturns the value from a counter database
Rule
Rule is created via RULE statement with the following syntax
RULE <rule_name>
LABEL <token(s) separated by comma> AS <label>
WHERE <boolean_condition>;
RULE "example_rule"
LABEL FeatureA, FeatureB AS "example_label"
WHERE true;
Rule names and label can contain any lower case alphanumeric ASCII characters and "_" symbol.
If-Else Clauses
ReQL support conditionals through if and else clauses.
<expression> if <boolean_condition> else <expression>;
Else clause is optional, as demonstrated by the example below.
# flip a coin
LET CoinFlip = 1 if random() > 0.5 else 0;
# increase the counter "coin_flip" key under "namespace"
incCount("namespace", "coin_flip") if CoinFlip == 1;
List Comprehension
ReQL does not have loops. Instead, ReQL has list comprehension similar to python's list comprehension.
The general syntax is of the form
[ <expression with ITER> FOR Iter IN <array_feature> ]
LET OddNumbers = [1, 3, 5, 7, 9];
LET EvenNumbers = [Iter + 1 FOR Iter IN OddNumbers];
Input Statement
When designing package to share with others, you can optionally specify a list of features that your package depend on.
This is accomplished via INPUT statement
OPTIONAL <feature_name> DOC "<doc_string>";
REQUIRE <feature_name> DOC "<doc_string>";
An input statement must have a DOC clause describing the feature.
An optional input created with OPTIONAL ... will have a default value of NULL.
REQUIRE UserLoginIp DOC "User login IP";
OPTIONAL UserEmail DOC "User login email";
This example declares a package with two input features, one required and one optional.
Import Statement
You can use IMPORT keyword to load other files or packages. Once a file or a package is imported, its features can be accessed via the dot operator ..
IMPORT <package_or_file>
WITH <input1> = <expr>,
WITH <input2> = <expr>,
...
WITH <inputN> = <expr>
;
where package_or_file is the location of the package and input1, input2 etc. are used to specify the exposed input of a given package.
Importing downloaded packages
When downloading packages using regle CLI tool, a folder called regle_pkg is created in the root of the rule directory.
Suppose our directory setup looks like this
./example_package
├── main.tw
├── other.tw
├── regle_pkg
│ └── github.com
│ └── regle_std_lib
│ └── ato_package
│ └── main.tw
└── regle_pkg.json
You can import ato_package package inside main.tw via
IMPORT "regle_pkg/regle_std_lib/ato_package";
Importing other tw files
Other tw files can also be imported by referencing the filename without the .tw extension
./example_package
├── main.tw
├── other.tw
└── regle_pkg.json
To import other.tw inside main.tw
IMPORT "other";
# we can now access features defined inside other file
LET OtherFeatureX = other.FeatureX;