After months of hard work, we finally released an app for iOS Relevant. With it, we break the existing foundations of interaction with services and content in the network, so that the user spends much less time on familiar things. This is achieved by presenting applications and web services in the form of cards (more
here ).
Cards, as independent interactive units, show what the future of mobile interfaces will be.

When we first started working on Relevant, only two things were clear to us: the cards should be beautiful and they should be universal. That is, their content can be generated from any source of information on the network with minimal restrictions. As for the prettiness, it deserves a separate article, and here we will not touch on it, but let's talk about universality.
Cards as JSON Objects
Since Relevant cards should be easy and downloadable, we decided to present them as JSON files containing instructions on how to access various information sources and APIs on the network and how to convert the data into the contents of the cards.

An unusually flexible card structure was required, which would not complicate the process of their creation. It should be possible, for example, to receive from the API an array of goods, and then receive detailed information about each of them. Moreover, data acquisition can occur through different APIs and then collect all of this together.
')
Thus, it became clear that the need to create a universal API aggregator: flexible, easily changeable and stored in external files. This will create an ecosystem where the cards will be able to develop, unlike applications whose contents are not accessible to the user, since the developers have simply crammed it up.
API non-standard
Web services and APIs are presented in a variety of forms. Some APIs, when they want to return a list, simply return an array, while others put it somewhere in the bowels of the returned object. Some use pagination, others take an explicit page parameter. [
It's not entirely clear what the implied difference is ] Add to this the hundreds of standards for the date and time format, a couple of URL standards and the random wrapping of integers and fractional numbers in quotes. Most developers who are trying to create an aggregation system for multiple APIs are quickly immersed in a multi-level hell of if-else blocks.
We wanted something more powerful. It was necessary to make our platform independent of the quality of the API design and its data. After much trial and error, Relevant Card's JSON began to look something like this:

Most of our API aggregation infrastructure rests on complex server and client systems. Nevertheless, the JSON-oriented language REL invented by us deserves special mention.
Quick introduction to REL
REL looks like an overshadowed JSON, but in essence it is a purely functional programming language with lazy immutable variables (that is, they are calculated and obtained only when necessary) and a dynamic scope.
Types and variables
Types in REL are standard JSON types: numbers, strings, objects, and arrays. In most cases, they parse directly. However, some objects have a special meaning. The key-value pairs of an object that has the key "_RETURN" are parsed as variable-value pairs. Variables are accessed using curly braces: "{variable_name}".
For example, the following object
{ "foo":1, "var":2, "_RETURN":{"_MATH":"{foo}+{var}"} }
REL is represented as number 3.
Functions
We often add new built-in functions in REL. These functions look like objects with certain special keys that start with an underscore. The function "_MATH" from the example above parses the string as a mathematical expression and returns its result.
Other built-in functions include "_URL", which loads JSON at a given address, and "_PATH", which searches for a value in a JSON object or an array. These two functions are the main ones used for the aggregation of the API in the REL Engine.
You can even create custom functions.
More information about this in the documentation .
Order management
Built-in functions such as {"_IF" :, "_THEN" :, "_ELSE":} and {"_LOOP": {"_ARRAY" :, "_EACH":}} are used to control the order of execution, but, unlike non-functional languages (such as C or Java), they always return a value.
More information about the current version of REL can always be found in the
documentation .
Also available is an evolving
library of cards with examples and descriptions on REL.
From translator
Translation in places is quite free, but not to the detriment of the meaning or content. Everything that does not relate directly to the original, made in the notes. The author of the publication is part-time and the author of the application, so that the source text is somewhat adware. I tried to shift the emphasis to the developed language. For a large number of links and a variety of appeals, refer to the original.
With suggestions, suggestions and comments, as usual, in drugs.