Qjs
Q is a language for capturing information structure. Think "JSON/XML schema" but the correct way. For more information about Q itself, see www.q-lang.io
Qjs is the javascript binding of Q. It allows defining Q schemas and validating/coercing data against them in an idiomatic javascript way.
Browser compatibility matrix
Example
Coming very soon now.
ADTs with Internal Information Contracts
Abstract Data Types can be defined and dressed using Qjs, provided you
register them at parsing time for name resolution purposes. Let take the usual
Color
example. (We "qualify" type names below only to avoid confusion, in
practice, one would probably use Color
everywhere.)
In Q,
QByte = .Number // should be defined more accurately, of course
QColor = .JsColor <rgb> { r: QByte, g: QByte, b: QByte }
In Javascript,
{ thisr = r; thisg = g; thisb = b;}Color { return tupler tupleg tupleb;}Colorprototype{ return r: colorr g: colorg b: colorb ;}
At parsing time:
schema = "..." // as shows above // you must let Qjs know about JsColor, in the following waysystem = Qjs; // dressing will then work as expectedcolor = system;
ADTs with External Information Contracts
Qjs also allows defining so-called 'external' information contracts for situations where implementing the dresser and undresser functions as show above is not possible or not wanted.
In Q,
QByte = .Number // should be defined more accurately, of course
QColor = .JsColor <rgb> { r: QByte, g: QByte, b: QByte } .ExternalContract
In Javascript,
{ thisr = r; thisg = g; thisb = b;}ColorContract = { return tupler tupleg tupleb; } { return r: colorr g: colorg b: colorb ; }
At parsing time:
schema = "..." // as shows above // you must let Qjs know about ExternalContract, in the following waysystem = Qjs; // dressing will then work as expectedcolor = system;
Rep: QType -> Javascript Type
The Rep
representation function mapping Q types to Javascript types is as
follows:
# Any is anything in javascript
Rep(.) = any javascript value/object/stuff
# Builtins are represented by the corresponding javascript type
# Supported: Number, String, Boolean, Date and your own abstractions (see below)
Rep(.Builtin) = Builtin
# Sub types are represented by the same representation as the super type
Rep(SuperType( s | ... )) = Rep(SuperType)
# Unions are represented by the corresponding javascript types. No guaranteed
# result in terms of types, as `^` (least common super type) is difficult to
# define properly in javascript.
Rep(T1 | ... | Tn) = Rep(T1) ^ ... ^ Rep(Tn)
# Sequences are represented through javascript Arrays.
Rep([ElmType]) = Array<Rep(ElmType)>
# Sets are represented through javascript Arrays. Qjs checks for duplicates,
# though.
Rep({ElmType}) = Array<Rep(ElmType)>
# Tuples are represented through standard javascript objects.
Rep({Ai => Ti}) = Object<{Ai: Rep(Ti)}>
# Relations are represented through Arrays of objects.
Rep({{Ai => Ti}}) = Array<Object<Ai => Rep(Ti)>>
# Abstract data types are represented through the corresponding javascript
# type when specified. ADTs behave as Union types if no type is bound.
Rep(.Builtin <rep> ...) = Builtin