Release 23rd September 2025
Change Control note Hiperspace --version 2.4.6 HiLang --version 2.4.6
Overview
This release introduces three new features for references to views, the Any polymorphic union type and Get<TEntity>(string sid) function. Together they provide the Hiperspace.DB functionality to combine any number of Hiperspaces in a single Graph view without duplication or copying.
View References
Views in Hiperspace are generated to combine all entities, segments, aspects and views that can be projected as the view, but also provide an additional role for sub-types and complex associations.
All references in Hiperspace can be navigated to either elements key or an index that matches the predicate used to reference it. The last release completed the optimization of view access to parts, this release adds indexing to efficiently access view items with criteria other than the key.
Indexed views
Consider the example of a Trading problem where Trades are booked in a Book, but each trade type {Fixed Income, Forex, Equity} can have specific properties for the product traded. When the view is referenced by a member other than the key (Book in this example), an index is created to efficiently access the set of matching values.
view Banking.Trade (Id : String) {Book : Banking.Book};
entity Banking.FI.Trade : Banking.Trade = Banking.Trade();
entity Banking.FX.Trade : Banking.Trade = Banking.Trade();
entity Banking.EQ.Trade : Banking.Trade = Banking.Trade();
entity Banking.Book (Id : String) [Trades : Banking.Trade (Book = this)];
Trades : Trade (Book = this)selects the set of Trade that have a reference to this Book. This access causes an index to be created in the view Trade that is inherited by each implementation.
Sub type
This UML diagram represents the logical view of the .hilang schema above. When a relational database is used, one of three strategies are normally followed:
- Direct: Each entity {Trade, FI_Trade, FX_Trade, EQ_Trade} is mapped separately, and joined as needed
- Down denormalization: Properties of the parent are duplicated in each of the sub-types and with context specific joining
- Up denormalization: Properties of each sub-type are added to the base type (optionally with aliases for duplicate names)
Hiperspace does not need denormalization the elements because types can inherit from a base type. The code entity FX_Trade : Trade = Trade; states that the entity FX_Trade inherits(:) from Trade and can be viewed(=) as a Trade
In the example above, each sub-type will be queried in parallel using the index on the Book reference
Modelled as Aspect
The schema could also have been modelled using aspect rather than realization, depending on business requirement, e.g.
- Convertible where final exchange is either equity or cash
- Hybrid where cashflow is calculated from either from a yield-curve or equity price
- Participation where the equity price uses FX exchange rates
entity Banking.Trade (Id : String) {Book : Banking.Book}
[FI : Banking.FI.Trade, FX : Banking.FX.Trade, EQ : Banking.EQ.Trade];
aspect Banking.FI.Trade;
aspect Banking.FX.Trade;
aspect Banking.EQ.Trade;
entity Banking.Book (Id : String) [Trades : Banking.Trade (Book = this)];
Aspects appear to be properties of the owning entity, so the choice has minimal impact on usage ( Banking.FI.Trade { YieldCurve = ... } vs Banking.Trade { FI = new Banking.FI.Trade { YieldCurve = ...}})
Segment / Aspect reference
Segments and Aspects are owned by the entity, segment, aspect that references them as an extension. They appear (*to users *) as a set property for segments, and value property for aspects, with the owner added transparently when a value is assigned.
<img src="https://www.cepheis.com/hiperspace/media/Sites/hiperspace/diagrams/segment.svg">
entity Customer [Accounts : Has];
segment Has (Account : Account);
entity Account [HasCustomer : Has (Account = this)];
HiLang translates the segment Has into an element CustomerHas (adding the key owner : Customer), and the segment Has is transformed into a view that CustomerHas provides. If there are no other implementations of Has (e.g. for a sub-account of Account) the view is pruned and not generated.
In this example Has is referenced by Account to provide a link from Account to Customer using the HasCustomerIndex. As a segment/aspect can be applied to any stored element, Has view includes the key owner : Any which in this case can be cast to Customer.
Any
The new type Any has been introduced to support segment/aspect views, and can be converted to any of the domain types like a union in F#. Unlike object, Any can be serialized and used anywhere in the schema, when a generic reference is required. Any is code generated by HiLang to include a constructor for the each of the domain types, together will cast operators to convert to each of the domain types. Elements also include a cast operator to convert to an Any when assigned.
Any uses constructors and conversion operators to behave like a base type for any domain element Any value = customer will use Customer’s operator Any function, Customer? value = any will use Any’s operator Customer function to return the value or null. Explicit cast functions are crerted for each element that could be stored.. for the Customer type it includes
- Customer() : cast the Any to a customer or null
- CustomerAsync() : async function to return the value (especially usefull for WebAssembly where network read may be required)
Any includes the functions
Type AnyType()to inspect the content of theAnyclass for match/switch statementbool Is<T>(): returns true if the content of theAnyis of typeTT? As<T>(): returns the value of theAnycast to the typeTTask<T?> AsAsync<T>(): returns the value of theAnycast to the typeTusing an async network call if necassary
Get(string sid)
SubSpace provides an object? Get (string sid) function that can be used to get an element in Hiperspace without knowing the type, just using the stringified key of the element. This function is now obsolete and has been replaced by TEntity Get<TEntity>(string sid) that allows the desired type to be retrieved.
This method was added for Hiperspace.DB that includes GraphSpace to aggregate Node/Edge/HiperEdge across domains. For GraphSpace it is necessary to call Get() with the SKey of a Node and then cast to Node which was not possible with object because elements do not need be viewable as a Node. GraphSpace uses Get<Node>(skey) for the lookup.