Closed gzsombor closed 3 years ago
It's a good idea. The semi-naive evaluation method lends itself well to this kind of incremental evaluation. Unfortunately, I don't think this is compatible with stratified negation.
If you're looking for a more flexible/streaming system, maybe check out differential dataflow?
Thanks for the suggestion. Initially, I saw differential dataflow, but it looked more complicated, and I liked your approach of declarative rules, but I guess, this is needed for this case. (If under stratified negation you meant a way to retract previously created relations)
Yes, stratified negation means rules that have a "does not exist" clause in them. For a trivial example,
use crepe::crepe;
crepe! {
@input
struct Number(i32);
struct Double(i32);
@output
struct Out(i32);
Double(2 * x) <- Number(x);
Out(x) <- Number(x), !Double(x);
}
This doesn't fit in the iterative model because relations don't monotonically grow; if you were to start with Number(2)
, then your output would be [Out(2)]
. However, if you then extend the input with Number(1)
, then Out(2)
would no longer exist due to the negation, and your output would be [Out(1)]
.
Negation is logically valid when stratified (i.e., no negative cycles between relations), and Crepe supports it. However, this stratification isn't compatible with incremental evaluation. That's why I think it's kind of tough to add this API.
Closing this now because the suggested design doesn't work. Note that you can call external functions within Crepe rules, though it doesn't work with async
. See this Reddit comment for an example.
It would be nice, if run wouldn't consume the crepe instance - or there were an incremental 'step()' function, which just returns the newly created relations - so if there is need to call external processes or even async functions, it can be implemented. I would imagine something like this:
What do you think?