Assigning goals in Clojure `core.logic`

The following Clojure code uses core.logic to solve the same logic problem with the same goals in two different orders. This choice of order makes you finish quickly and the other freezes.

 (use `clojure.core.logic) ;; Runs quickly. Prints (1 2 3). (clojure.pprint/pprint (run* [q] (fresh [x] (== x [1,2,3]) (membero qx)))) ;; Hangs (clojure.pprint/pprint (run* [q] (fresh [x] (membero qx) (== x [1,2,3])))) 

Is there a general solution or common practice to avoid this problem?

+6
source share
2 answers

If you intend to use membero , there is no general solution to this problem. Calling membero with fresh vars will cause it to generate all (read, endless) possible lists for which q is a member. Of course, lists that are larger than 3 are not applicable, but since you used run* , it will continue to blindly try lists that exceed score 3, although each of them will fail.

You can write a better version of membero in new versions of core.logic using the framework of restrictions, but the details of how to do this are likely to change in the coming months. Until you have a reliable public api for defining restrictions, you are stuck with such subtle problems with ordering and without interruption that Prolog is worried about.

+3
source

Here is my understanding:

With core.logic you want to reduce your search space as soon as possible. If you first set the membero constraint, the start will begin by searching the membero space and returning to the error caused by the == constraint. But the space of membero HUGE, since neither q nor x are unified or at least bounded.

But if you first place the constraint == , you immediately combine x with [1 2 3] , and the search space for membero now explicitly limited to x elements.

+7
source

All Articles