3

I've been playing with Prolog recently and getting my head around how to represent some tasks I want to do with it, which are largely about having a database of facts and doing simple queries on it, joining multiple facts together.

But I want to use this is in a context where I'm writing Clojure. And it seems like core.logic should do what I want.

But I'm naively finding it difficult to see how to put basic Prolog predicates into core.logic.

For example, how should I represent something as simple as this in core.logic :

person(phil).
person(mike).
food(cheese).
food(apple).
likes(phil,apple).
likes(phil,cheese).

And a query like

food(F),person(P),likes(P,F)

Most introductions I can find are heavy on the logic programming but not the data representation.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
interstar
  • 26,048
  • 36
  • 112
  • 180
  • Have you looked at the [tests](https://github.com/clojure/core.logic/blob/master/src/test/clojure/clojure/core/logic/tests.clj) posted with core.logic? more [tests](https://github.com/clojure/core.logic/blob/master/src/test/clojure/clojure/core/logic/pldb/tests.clj) If this is acceptable, I can make it an answer so that others can see this question has an accepted answer. – Guy Coder Jan 16 '20 at 12:06
  • Ok, so using db-rel and db? – interstar Jan 16 '20 at 12:14
  • There's no equivalent of Prolog’s defining relations and data at the same time? – interstar Jan 16 '20 at 12:15
  • Oops. Forgot to mention I have never used Clojure. I was writing an answer and the facts looked easy, but the the query has me confused on how to convert to *core.logic* so I will not be posting an answer. – Guy Coder Jan 16 '20 at 12:16
  • Another way that might work for you would be to use [SWI-Prolog](https://www.swi-prolog.org/) and Java interface [JPL](https://www.swi-prolog.org/FAQ/Java.html). Another tool I am aware of but have not used. – Guy Coder Jan 16 '20 at 12:19
  • 1
    Also noticed that `core.logic` is based on [minikanren](http://minikanren.org/) which might be of use. – Guy Coder Jan 16 '20 at 12:21
  • Also found [this](http://mullr.github.io/micrologic/literate.html) which appears to explain how to convert *Prolog* to *minKranren* for use with *core.logic* – Guy Coder Jan 16 '20 at 12:24
  • in [Racket](https://stackoverflow.com/q/50568981/849891), I can just ``(define (person n) (conde [(== n 'phil)] [(== n 'mike)])) (define (food n) (conde [(== n 'cheese)] [(== n 'apple)])) (define (likes n x) (conde [(== n 'phil) (== x 'apple)] [(== n 'mike) (== x 'cheese)])) (define (test) (run* (q) (fresh (a b) (== q `(,a ,b)) (likes a b))))`` and running `(test)` produces `'((phil apple) (mike cheese))`. if you know of any readily avilable online environment where one could try the clojure core.logic code, I could try it there – Will Ness Jan 16 '20 at 15:34

1 Answers1

2

As Guy Coder said, the PLDB package under core.logic solves exactly this kind of problems:

(db-rel person p)
(db-rel food f)
(db-rel likes p f)

(def facts (db
  [person 'phil]
  [person 'mike]
  [food 'cheese]
  [food 'apple]
  [likes 'phil 'apple]
  [likes 'phil 'cheese]))

(with-db facts (run* [p f] (food f) (person p) (likes p f)))

=> ([phil cheese] [phil apple])    p=phil,f=cheese   or   p=phil,f=apple
Marc Dzaebel
  • 425
  • 4
  • 12