Take the 2-minute tour ×

Two related questions in one:

Can Clojure's core.logic module perform arithmetic, logical comparison, etc, like ordinary Prolog? I am envisioning something like the following:

(defrel points person n) 
(fact :bob 2)
(fact :charlie 3)
(run* [q] (fresh [x y] 
   (points :bob x) 
   (points :charlie y) 
   (< x y) 
   (== q (+ x y))))

=> (5)

In this example, neither the logical comparison (< x y) nor the attempted binding of q to (+ x y) works. I suppose that this is because I'm working with LVars, not integers at this point, and I can't make these comparisons because the symbols aren't yet bound. But it works in prolog:

points(bob, 2).
points(charlie, 3).
?- points(bob, X), points(charlie, Y), Result is X + Y.

=> Result = 5.

In a similar vein, can I somehow use Clojure functions (which return booleans or other "truthy" values) as logic predicates? In other words, to use functions to tell Minikanren which terms unify or not. Something along the lines of:

(defmagic startswithhi-o [v]
  (.startsWith v "hi"))
(defrel person n)
(fact person "bob")
(fact person "hillary")
(run* [q] 
   (fresh [n]
     (person n)
     (startswithhi-o n)
     (== q n)))

=> ("hillary")

If I try things like this I get errors also complaining that the LVars aren't bound. Is there a way to do this?

Lastly if anyone has read this far, I might as well ask: are there plans to incorporate probabilistic logic into core.logic, along the lines of:

http://dtai.cs.kuleuven.be/problog/ ?

I'm not holding my breath but it would be awesome!

share|improve this question
Many thanks to both of you -- can't wait to see what the immensely talented core.logic team comes up with next! –  gilesc Oct 6 '11 at 21:47
add comment

2 Answers

up vote 8 down vote accepted

Non-relational arithmetic is possible via project.

(run 1 [q]
   (fresh [x y]
        (== x 1)
        (== y 2)
        (project [x y]
                 (== q (+ x y)))))

I believe the Prolog example given is also non-relational.

The second half of your question can also be solved via project, but you must be careful that you always input a ground value.

(defn startwith [x]
    (project [x]
         (== true (.startsWith x "hi"))))

PS: Hold your breath for Constraint Logic Programming to come to core.logic!

share|improve this answer
add comment

I believe you have to "project" (nonrel/project) a logic variable to its binding before you can apply a function to it:

(defrel points person n) 
(fact points :bob 2)
(fact points :charlie 3)
(run* [q] 
  (exist [x y] 
    (points :bob x) 
    (points :charlie y) 
    (project [x y]
      (== true (< x y)) 

Note that exist substitutes for fresh in the original snippet and the additional argument for the fact declarations.

share|improve this answer
add comment

Your Answer


