Skip to content
Jaskirat Rajasansir edited this page Nov 3, 2021 · 2 revisions

Interface Library

This library has been added to allow implementations of common logic to be implemented by an external system. This allows easier integration with an existing system.

Defining an Interface

An interface should be required if you do not want to define an implementation but expect the system that the library will run in to have the interface defined.

Interface definitions live within .if.cfg.interfaces:

  • lib: The library that the interface lives within
  • ifFunc: The interface that must be implemented
  • implFunc: The implementing function
    • This must be non-null at the time the interface binding is performed otherwise an exception will be thrown
    • This can either be a function reference or a function body

Interface Binding

If a library requires the interfaces to be implemented, it should call .if.bindInterfacesFor[bindLib; overwrite]. This will ensure that the interface functions are set with the implementations defined at that point.

If any interfaces within the specified bindLib are not defined at this point, an exception will be thrown.

Interface bindings can be changed at any point and re-initialised by ensuring overwrite is set to 1b.

Any interface bindings defined before the Interface library is initialised must have default implementations otherwise an exception will be thrown

Default Interfaces

The default interfaces that are defined by require.q on initialisation are:

Library Interface Function Implementation Function
log .log.if.trace .require.i.log
.log.if.debug .require.i.log
.log.if.info .require.i.log
.log.if.warn .require.i.log
.log.if.error .require.i.logE
.log.if.fatal .require.i.logE

Examples

Standard require.q Usage

When using require.q, the interfaces above are defined. These do not need to re-bound on every library initalisation unless they have been changed.

// if.q is automatically loaded and initialised by require.q
//   Log interfaces are defined and defaults to standard out and standard error are set
q) .require.init[]
...
Library initialisation function detected [ Func: .if.init ]
Binding implementations to library interfaces [ Library: log ] [ Interfaces: 6 ]
...

q) .if.cfg.interfaces
lib ifFunc       | implFunc
-----------------| ----------------
                 | ::
log .log.if.trace| `.require.i.log
log .log.if.debug| `.require.i.log
log .log.if.info | `.require.i.log
log .log.if.warn | `.require.i.log
log .log.if.error| `.require.i.logE
log .log.if.fatal| `.require.i.logE

Library Provided Override of Existing Interface

log.q provided overrides for the default log interfaces defined above.

In this case, it overrides the implementing functions and re-binds the interfaces for other libraries to use.

// When the log library is loaded, it overrides these default implementations
q) .require.lib `log
...
Library initialisation function detected [ Func: .log.init ]
Binding implementations to library interfaces [ Library: log ] [ Interfaces: 6 ]
...

q) .if.cfg.interfaces
lib ifFunc       | implFunc
-----------------| -----------
                 | ::
log .log.if.trace| `.log.trace
log .log.if.debug| `.log.debug
log .log.if.info | `.log.info
log .log.if.warn | `.log.warn
log .log.if.error| `.log.error
log .log.if.fatal| `.log.fatal

Caller Defined Interface

In this example, a library defines a function it requires but does not provide an implementation itself

// myLib.q
// This library requires the function '.extern.needThis' to be defined, but doesn't provide an implementation itself

.if.setImplementationsFor[`myLib; enlist `ifFunc`implFunc!(`.extern.needThis; `)];

.myLib.init:{
    .if.bindInterfacesFor[`myLib; 0b];
 };

In the case where no implementation is provided before library initialisation, an exception is thrown:

// No implementation provided
q) .require.init[]
...
q) .require.lib `myLib
Loading library: myLib
Loading /home/jas/git/kdb-common/src/myLib.q
Library initialisation function detected [ Func: .myLib.init ]
Interface Error: Missing implementations for library interfaces [ Library: myLib ]
 Missing interfaces: .extern.needThis
Init function (.myLib.init) failed to execute successfully [ Lib: myLib ]. Error - MissingInterfaceImplementationException

Once defined prior to init, the library intialises OK:

// Provide an implementation
q) .require.init[]
...
q) .if.setImplementationsFor[`myLib; enlist `ifFunc`implFunc!(`.extern.needThis; { -1 "Implemented: ",.Q.s1 x })];

q) .require.lib`myLib
Library initialisation function detected [ Func: .myLib.init ]
Binding implementations to library interfaces [ Library: myLib ] [ Interfaces: 1 ]
Initialised library: myLib

q) .extern.needThis "Test"
Implemented: "Test"
Clone this wiki locally