-
Notifications
You must be signed in to change notification settings - Fork 18
require.q
This library is inspired by RequireJS and other import systems within JavaScript applications. It allows the loading of libraries into a kdb+ process and manages dependencies between them to aid separation of code into small, reusable components.
We define a library to be a collection of q-script files that are related by a common prefix. In the simplest case, a library can be a single q-script with the name equalling the library name (e.g. log.q provides the log library). We also assume that the library name matches the namespace used for that library (e.g. log library uses .log namespace).
To allow code within a single library to also be split into separate files, files with the same common prefix are assumed to be the same library. The suffixes used to determine this are: .q, .k, .*.q, .*.k, .q_, .*.q_. Note that with the prefixes .*.q, .*.k and .*.q_, log.q and, for example, log.extra.q would be classified as the same library and would both be loaded as part of the log library.
To start using Require within your application, you must load and initialise the library manually:
q) system "l src/require.q"
q) .require.init[]
Require library initialised [ Root: :C:\Users\jasra_000\git\kdb-common ]
Library root location refreshed [ File Count: 29 ]There are 2 ways to initialise the library:
-
.require.init[]: This will use the current working directory as the root folder to discover files -
.require.init path: This will use the specified path as the root folder to discover files
Once Require is loaded and initialised, you can then use .require.lib to load any other library. This function will search for a library with the specified name and load all matching files into the current process. If there is a function *lib*.init, it will be executed with no arguments after all files are loaded.
If you need to perform some other set up or configuration after the files are loaded but before the initialisation function is run, you should use .require.libNoInit to load the library, run you custom code and then run .require.lib to initialise it.
.require.lib can also be used to define dependencies between libraries that you write. Use it at the top of your library.
For example, if you need to use .type.isInteger from the type library in some new code, you can do the following:
// your-lib.q
/ Loads the "type" library (if not already loaded)
.require.lib `type;
.lib.intSum:{[x;y]
if[(not .type.isInteger x) || not .type.isInteger y];
'"IllegalArgumentException";
];
:x + y;
}The Require library keeps track of all libraries that are loaded (and initialised). This is used internally to know which libraries to load from disk but can also be used to manually see which libraries are within the process.
The table .require.loadedLibs provides this detail:
q) .require.lib`ns
...
q) .require.loadedLibs
lib | loaded loadedTime inited initedTime files
-------| -------------------------------------------------------------------------------------------------------------------------
require| 1 2017.03.28D11:02:03.627790000 1 2017.03.28D11:02:03.627790000 ()
type | 1 2017.03.28D11:02:03.627790000 0 ,`:C:\Users\jasra_000\git\kdb-common/src/type.q
ns | 1 2017.03.28D11:02:03.627790000 0 ,`:C:\Users\jasra_000\git\kdb-common/src/ns.q
As part of Require's initialisation, it uses the current working directory or specified directory as the root for all files it can load. The current root directory in use is stored in .require.location.root and all the discovered files in .require.location.discovered.
As this is only done on initialisation, any added or removed files will not be reflected in this list. You should use .require.rescanRoot to update the list before attempting to load a new library.
If you require a more complex list of files that Require can use, you can manually set the list of files in .require.location.discovered prior to calling .require.init.
The following exceptions can be thrown when using the Require library:
-
LibraryDoesNotExistException: If there are no files that match the library requested -
LibraryLoadException: If any of the matched files fail to load into the process -
LibraryInitFailedException: If a initialisation function exists for the library and it does not execute successfully -
UnknownLibraryException: If you attempt to initialise a library that has not been loaded by Require
Copyright (C) Sport Trades Ltd 2017 - 2020, John Keys and Jaskirat Rajasansir 2020 - 2024