Search code examples
clojureclojure-core.logic

How to write your own simple constraint function in core.logic?


I just read the primer for core.logic. It makes sense so far, but I'm not sure where to go to learn more.

Let's say I wanted to write my own constraint, sort of like the membero shown in the primer. This one is called vectoro and constrains things to be a vector.

(defn vectoro [s] ???)

(run* [q]
  (conde
    [(== q [1 2])]
    [(== q :a)])
  (vectoro q))

Now I want that to return [1 2]. How do you write vectoro? Is this documented anywhere?


Solution

  • There's a core.logic pred macro that makes this easy:

    (run* [q]
      (== q [1 2])
      (pred q vector?))
    => ([1 2])
    
    (run* [q]
      (== q '(1 2))
      (pred q vector?))
    => ()
    

    Here's how you might define a vectoro function/contraint (but realize this is essentially the exact same thing pred is doing):

    (defn vectoro [a]
      (project [a]
        (== true (vector? a))))
    

    project is used to operate on the actual/concrete value of the logic variable (LVar). We can then use the plain old predicate vector? and require the result be true. This also works with your example program:

    (run* [q]
      (conde
        [(== q [1 2])]
        [(== q :a)])
      (vectoro q))
    => ([1 2])
    
    (run* [q]
      (conde
        [(== q '(1 2))]
        [(== q :a)])
      (vectoro q))
    => ()