1

Prolog mixes logic (fallible) goals, and (infallible) processes like write/2 or assert/1. Is it possible to do so with Clojure's core.logic?

For example:

(pldb/with-db myFacts
   (l/run* [x y] 
       (person x)
       (println "we found a person!")
       (likes y x)
   )
)

It looks like this can't work because (println ...) is a Clojure function embedded in a core.logic run (which is supposed to contain only conditions/constraints I'm guessing).

More interestingly, I would like to be able to assert new facts in the midst of checking logical conditions like in Prolog:

liked(x,y):-
    person(x),
    assertz(likable(x)),
    likes(y,x).

Which would approximatively look like this in core.logic I'm guessing:

(pldb/with-db myFacts
   (l/run* [x y] 
       (person x)
       (def newFacts (-> newFacts (pldb/db-fact likeable x)))
       (likes y x)
   )
)

Those examples are silly but, in general, the question is about inserting procedural commands in the midst of constraint checking in core.logic like it is done in Prolog.

One concrete application of that, for instance, would be the capability to collect arcs in the recursive traversal of a graph by using assertion. But, unless I am mistaken, that's only possible if we have the possible to mix assertion with logical conditions.

Thank you very much for your help and guidance in this.

UPDATE: I think I might have figured it out: including a Clojure statement is fine but it must return true ; unlike in Prolog, those functions don't automatically "succeed". So all we need to add is: (l/== (println "hello") true)) Does it sound correct? FYI, this post was really helpful: https://ask.clojure.org/index.php/9546/can-core-logic-ask-questions

  • Martynas M replied to your question in #core-logic channel of [Clojurians Slack](https://clojurians.slack.com/): 'IMO you don't ever control how the logic will progress. So you probably can't. But even then what would a person expect... what if the solver will decide to run your expression 1M times? I don't know if it makes more sense than reacting to the results themselves. Also one more problem with shimming the code is that it would force the solver to solve from the "side" that would input into your code.' So might cause trouble if the solver decides to run an expression more than once. – user2609980 Jun 09 '22 at 11:49
  • Thank you for that reference! It makes sense that we can't really do that in core.logic (because of the relational paradigm maybe?). It looks like I can recreate the same behavior though using a combination of (l/project [...] (l/== (myClojureFunction) ...)) for calling outside core.logic and (l/condu ...) for the control flow. Does it seem right? – Hugolin Bergier Jun 11 '22 at 22:23

0 Answers0