Imports
While using NQE, you may find yourself needing the same functionality in multiple queries. Imports allow you to share values and functions without copying and pasting code. In the following example, we will write logic for a car shop, utilizing imports to make our code easy to read and update.
For our car shop, we will need to keep a record of the cars in our inventory. Our car inventory will be represented as a
list of records. For simplicity, our car shop will only hold one car for each car model. Let's create a directory
called Shop and within that directory a file called Inventory. These are the contents of the file Shop/Inventory:
export inventory =
[{ make: "Tesla", model: "3", isOnSale: true, isClean: false },
{ make: "McLaren", model: "F1", isOnSale: false, isClean: false },
{ make: "Toyota", model: "Prius", isOnSale: true, isClean: true }
];
Note that we marked the value inventory as an export, which means that we can now access the value cars in files
other than Shop/Inventory, so as long as we import Shop/Inventory. Now let's write a check that ensures that all
cars that are on sale are clean, which we will write in the file Checks/On Sale Cars Are Clean:
import "Shop/Inventory";
foreach car in inventory
select {
make: car.make,
model: car.model,
// A car is a check violation if the car is on sale and not clean
violation: car.isOnSale && !car.isClean
}
We import from a file with a statement of the form import "path/to/module"; where path/to/module is the location of
the file we would like to import. The path is absolute (not relative) and slashes separate directories and the file
name. Note also that when we import a file, we only have access to those functions and variables that are
marked export.
Now that we have defined our car inventory as an export, we can use our car inventory in multiple different checks.
Let's now write a check that we are only selling car makes that we like in a file called Checks/Sell Only Liked Makes:
import "Shop/Inventory";
// We only sell good makes at our shop
makesWeLike = ["Tesla", "McLaren", "BMW"];
doWeLikeMake(make) = make in makesWeLike;
foreach car in inventory
where car.isOnSale
select { make: car.make, model: car.model, violation: !doWeLikeMake(car.make) }
But there's a new issue at our shop: we are cleaning cars with makes that we don't like... That simply won't do! Let's
write a check that ensures that any car that we don't like is dirty, in a file
called Checks/Unliked Car Makes Are Dirty:
import "Shop/Inventory";
// We only sell good makes at our shop
makesWeLike = ["Tesla", "McLaren", "BMW"];
doWeLikeMake(make) = make in makesWeLike;
foreach car in inventory
where !doWeLikeMake(car.make)
select { make: car.make, model: car.model, violation: car.isClean }
See how we copy-and-pasted the doWeLikeMake function in order to find out whether we like a car make? As well as
values, we can also export and import functions, so long as we tell NQE what type the function's arguments are. This
will help us to avoid duplicating the function doWeLikeMake between these two new checks. Let's export
our doWeLikeMake from a file called Shop/Makes We Like:
import "Shop/Inventory";
// We only sell good makes at our shop
makesWeLike = ["Tesla", "McLaren", "BMW"];
export doWeLikeMake(make: String) = make in makesWeLike;
Now we can rewrite the check in Checks/Sell Only Liked Makes to:
import "Shop/Inventory";
import "Shop/Makes We Like";
foreach car in inventory
where car.isOnSale
select { make: car.make, model: car.model, violation: !doWeLikeMake(car.make) }
And we can also rewrite the check in Checks/Unliked Car Makes Are Dirty:
import "Shop/Inventory";
import "Shop/Makes We Like";
foreach car in inventory
where !doWeLikeMake(car.make)
select { make: car.make, model: car.model, violation: car.isClean }
The rewritten checks are a significant improvement! Imports and exports allowed us to reuse code with ease. Also, notice
that if we ever want to add another brand we like, we can just add a new make, say Ferrari, to makesWeLike:
// We only sell fancy makes at our shop
makesWeLike = ["Tesla", "McLaren", "BMW", "Ferrari"];
Importing from Forward Library
To import from the Forward Library,
start the path with @fwd.
Here is an example of that.
import "@fwd/Interfaces/Interface IPs";
foreach device in network.devices
foreach subnet in getAllIfaceSubnets(device)
select { Device: device.name, Subnet: subnet }