Fork me on GitHub
Oliver George00:09:28

In my early experimentation with clara I ended up with infinite loops when firing rules. They were non-terminating due to rules which are directly or indirectly affected by the facts they insert.

Oliver George00:09:46

I went looking for documentation around this. I can't see anything apart from an issue about a :no-loop flag.

Oliver George00:09:38

Direct question: is Clara smart enough to avoid infinite loops based on bad rules?


@dadair not sure if I understand. But my rules was in a loop inside the fire-rules.


@olivergeorge are you asking if Clara can solve the Halting problem?


Joking aside: No Clara can’t really detect the loops


The RHS can do arbitrary things


There is no way to know that something that “looks like a cycle” at runtime isn’t going to eventually stop cycling


Clara could assume if a cycle of rules was happening “too many times” that it should stop


In Drools (popular Java-based rules engine that I often reference since it was used a lot in the industry) there was a “fire until halt” sort of method I believe it was called. This allowed to have a sort of “timeout” feature that the rules would stop if they reached a certain threshold of time, steps, # rule firings, etc. So something like that is feasible to implement, but not in Clara right now.


I do tend to try to avoid using something like :no-loop too and instead setup the rules in a way where they logically won’t loop. :no-loop starts to go against the logical truth maintenance in some cases.


Understandably, there are cases where it is sort of hard to think about how you can make the rule logic you want not form a logical loop.


There is work logged for Clara to assume by default that after a certain number of iterations of looping that the rules were written incorrectly and throw an exception:


I agree with @mikerod ‘s comments - perhaps another way of thinking about it is that if you just write a normal infinitely recursive function, Clojure or any other programming language can throw a StackOverflowException but can’t automatically recover from it - the language would have to guess what the programmer actually wanted to do in order to accomplish that


I see Clara’s handling of infinitely looping rules as similar - there’s no way for Clara to guess what the user actually wanted to do


Cool, forgot you logged that issue before


Is there a way for someone to override what is printed when an exception is thrown? I have a fact with a very large map and when an exception is thrown it tries to print it as a binding and the REPL basically becomes unresponsive.


@dadair I’ve had similar issues before


Trying to think of a workaround


I think printing the bindings directly in the exception message can be a little ambitious since sometimes there are really large bindings. They can be really big due to things like acc/all too


From the REPL, you may be able to get by with try + catch around when you run the rules?


so catch the exception to not let it print its default dump


if you are encountering the error using something like clojure.test it automatically catches and prints exceptions I think. You may be able to override that behavior as well