Goals
- Most importantly this is a research task, to both expand our understandings of the different domains, and also to discover the limits of what is possible here.
- Lowest level model that is executable, or transformable to be executable, without the need for bytecode munging (analysis, transformation or generation).
- Indexes etc must be proved by arguments. High level languages may generate these through analysis, when it targets the execution model.
- Should be designed to map well to a Fluent level builder
- This will allow low level engine feature design and testing, independent of any language. Which means we can innovate at an engine level, without having to worry about the language layer.
- The fluents should be good enough to be of interest to Java developers, looking to address functional reactive programming
- The Execution Model should be generic enough to map in multiple domains. It will be a low level dataflow model in which you can address functional reactive programming models, but still use it to build a rule based system out if it too.
- Initially we'll focus on Rule Based domains. But this should extend out to the full range of functional reactive programming. It is not expected the same execution engine is used for both simpler functional reactive streams (that are insert only) and datasources that support insert/update/delete.
- While the model should try to be expansive as possible, we should also consider adapters too. So that for instance RxJava Observables or Camel Routes can be wrapped and integrated. This is not instead of, but in complimentary.
- The "LHS" DataFlow should become a sort of literal, in much the same way as LinQ and RxLinQ. This dataflow literal can simply process the vars in scope, or be abstracted and separated (via subscription) to a datasource.
- The idea of Patterns and other high level constructs should not be included. Instead There is a DataFlow and the DataFlow has Elements. A typical rule based DataFlow can map to 'and', 'or', 'expr' and 'input' Elements. Each 'input' declares the variable makes available, and each 'expr' declares the inputs it processes. From this the Elements can be ordered, by dependency, if necessary.
- DataSource will be separate from Rules now. DataSource is generic and it's concrete implementations indicate it's role.
- DataStore is a DataSource that supports insert/update/delete. It may reactive (push) of passive (pull/query).
- DataStream does not support update or delete, it propagates as an insert (or send or emit or observe) only. It will attempt to delay creation of things like FactHandles until necessary, such as entering Windows or Joins
Example fluent to build the executable model. Notice the optional index declarations. The other downside is arguments must be repeated, the first two are the variables it unifies (uses) against. The second the ones actually passed into the lambda, unfortunately those cannot exist outside lambda, hence the duplication. The upside is using generics it makes everything type safe, and inferable via reflection.
Variable<Person> x = new Variable<Person>("x", Person.class); Variable<Person> y = new Variable<Person>("y", Person.class); Variable<Person> z = new Variable<Person>("z", Person.class); DataSource<Person> persons = new DataSource<Person>(); public void test1() { //String x = null; and(input(x, () -> persons). // return a Map, List or reference to DataSource input(y, () -> new ArrayList<Person>()). set( z, () -> new Person() ). expr( x, (xp) -> xp.name.equals("hello") ). expr( x, y, (xp, yp) -> xp.age == yp.age) ). and( expr(x, xp -> xp.name.equals("hello")). expr(x, y, (xp, yp) -> true, // return true, as expression handled by index index(x, int.class, xp -> xp.age), index(y, int.class, yp -> yp.age))); }
Comments