The following Clojure code uses core.logic to solve the same logic problem with the same goals in two different orders. This choice of ordering causes one to finish quickly and the other to hang.
(use `clojure.core.logic)
;; Runs quickly. Prints (1 2 3).
(clojure.pprint/pprint (run* [q] (fresh [x] (== x [1,2,3])
(membero q x))))
;; Hangs
(clojure.pprint/pprint (run* [q] (fresh [x] (membero q x)
(== x [1,2,3]))))
Is there a general solution or common practice to avoid this problem?
If you’re going to use
memberothere is no general solution to this problem. Callingmemberowith fresh vars will cause it to generate all (read, infinite) possible lists for whichqis a member. Of course lists larger than 3 don’t apply – but since you’ve usedrun*it will continue blindly trying lists larger than count 3 even though each one will fail.It’s possible to write a better version of
memberoin newer versions of core.logic using the constraint infrastructure, but the details of how one might do this are likely to change over the coming months. Until there’s a solid public api for defining constraints you’re stuck with the kind of subtle ordering and non-termination issues that trouble Prolog.