Query¶
Creating an unchanging value is a very simple thing to do: just instantiate the things you want. Programming is about change, and that’s where the most important features of Basilisk are targetted.
The query module (which we usually bind to b$ to keep our code clutter-free) allows you to create new versions of values in a way which is simple to understand.
- basilisk.query.replace(initial : any, path : PathSegment, []changed: any) → any¶
Given an initial value, this returns a new value which has changed substituted at the end of path.
For example:
var a = new Person({ 'name': 'joe', addresses: new basilisk.Vector.from([ new Address({ country: 'RSA' }), new Address({ country: 'United Kingdom' }) ]) }), b; b = b$.replace(a, ['addresses', b$.at(0), 'country'], 'South Africa'); a.addresses.get(0).country; // 'RSA'; b.addresses.get(0).country; // 'South Africa';
Parameters: - initial – a value you wish to derive a new value from.
- path – PathSegments (or strings which will be converted into prop path segments.)
- changed – the value to substitute at the end of the path in the newly created return value.
- basilisk.query.swap(initial : any, path : PathSegment, []swapFn : function(value) -> any) → any¶
Like replace, but calls swapFn with the current value at the end of the chain, and replaces the end value with the result.
For example:
var a = new Person({ 'name': 'joe', addresses: new basilisk.Vector.from([ new Address({ country: 'RSA' }) ]) }), b; b = b$.swap(a, ['addresses', b$.at(0), 'country'], function (country) { // normalise common abbreviations of South Africa if (country === 'RSA' || country == 'ZA') { return 'South Africa'; } else { return country; } }); a.addresses.get(0).country; // 'RSA'; b.addresses.get(0).country; // 'South Africa';
Parameters: - initial – a value you wish to derive a new value from.
- path – PathSegments (or strings which will be converted into prop path segments.)
- swapFn – A function to be called with the value at the end of the path. The return value will be substituted at the end of the path, in the newly created result.
- basilisk.query.value(root : any, path: PathSegment[]) → any¶
Applies the path to the specified root and returns the current value at the end of the chain.
- basilisk.query.path(...pathsegments) → Path¶
Create a new Path object from the specified Path Segments. strings will be converted into prop segments.
Parameters: pathsegments – string‘s or PathSegment‘s which will be stored and can be used to swap or apply
Path¶
A Path is an ordered list of Path Segments, which can be applied to many values to produce updated versions.
- class Path¶
(Interface) A Path which can be applied to many different values.
- swap(initial : any, swapFn : function(value) -> any) → any¶
Like the query.swap method, but with this path applied.
- replace(initial : any, changed : any) → any¶
Like the query.replace method, but with this path applied.
PathSegment¶
The swap and replace functions are wrappers around Path objects, which are made up of path segments. A path object allows you to
- find the next value in a chain.
- replace that value with a new one.
This is where the Struct interface becomes very important:
var b$ = basilisk.query,
Person = basilisk.makeStruct(['name', 'age']),
joe = new Person({ name: 'Joe Bloggs', age: 32 }),
changed,
propSegment;
// basilisk.query.prop is a path segment that looks at Struct properties.
propSegment = b$.prop('age');
propSegment.current(joe); // returns '32'
changed = propSegment.replace(joe, 35);
/**
Changed will now be:
{
name: 'Joe Bloggs',
age: 35
}
*/
The path constructor (called by swap or replace) will convert any plain string to a prop segment.
The basilisk.query.at path segment will work with any collection or object which has both .get and .set methods. The .set method must produce a new value with the key replaced. Keys can be any type that the collection understands (and collections should throw an error if they aren’t).
For example:
var b$ = basilisk.query,
numbers = basilisk.Vector.from([10, 11, 12, 13]),
segment;
segment = b$.at(3);
segment.current(numbers); // returns 13
segment.replace(numbers, 9); // returns V([10, 11, 12, 9])
Any object can be used in a path, as long as is has all the methods on the PathSegment interface.
- class PathSegment¶
(Interface) Any object which has all the methods on the PathSegment interface can be used in a Path. PathSegments must be immutable - they can be cached and re-used.
- current(from : any) → any¶
Given an object, descend a step into it as appropriate for the segment.
For example, prop segments simply do value[key] where key is configured at creation time.
Returns: the next value in the path.
- replace(from : any, changed : any) → any
Perform the update appropriate for the path segment on the from parameters, using changed as the property.
Basic Path Segments¶
Basilisk comes with a small set of generic path segments, which
- basilisk.query.prop(propertyName : string) → PathSegment¶
Creates a PathSegment which will descend and replace a single property in a Struct.
- basilisk.query.at(key : any) → PathSegment¶
Creates a PathSegment which will apply the key to the .get and .set methods of a collection.