core-logic

2018-10-28T19:43:30.004400Z

Just kicking around core logic with one of the initial tutorials and I have this basic definition set:

(pldb/db-rel parent x y)
(defn grandparent [x y]
  (logic/fresh [z]
      (parent x z)
      (parent z y)))
Now if I do this:
(apply pldb/db
    [[parent :Bob :Mike] [parent :Mike :John]])
#_=> {"logic.test/parent_2"
 #:cljs.core.logic.pldb{:unindexed #{(:Bob :Mike) (:Mike :John)}}}
I get the result I expect, but when I do this:
(apply pldb/db
    [[grandparent :Bob :John] [parent :Mike :John]])
#_=> {nil #:cljs.core.logic.pldb{:unindexed #{(:Bob :John)}},
 "logic.test/parent_2"
 #:cljs.core.logic.pldb{:unindexed #{(:Mike :John)}}}
I get the above which I don’t understand, how do I not have the (:Bob :Mike) relation? Have I misunderstood something? Note: I have tried: (grandparent :Bob :John) => #object[Function] ((grandparent :Bob :John)) => #object[cljs.core.logic.Inc] but feeding them into the apply pldb/db statement just gave exceptions, so I thought I was going down the wrong track…

2018-10-28T21:31:22.004900Z

you can't really call things in core.logic like that

2018-10-28T21:31:53.005500Z

the grandparent function is returning a a goal, and the goal has to be inside a call to run or run* to see what the result is

2018-10-28T21:33:51.006500Z

I haven't really used pldb, but my guess is to create facts you call the name of the relation as a function

2018-10-28T21:34:16.007Z

(parent :Bob :Mike) not [parent :Bob :Mike]

2018-10-28T21:34:48.007400Z

but I might be wrong there

2018-10-28T21:36:34.007900Z

and I am, the pldb tests show the vector thing (at least on the clojure side) https://github.com/clojure/core.logic/blob/master/src/test/clojure/clojure/core/logic/pldb/tests.clj#L15

2018-10-28T21:38:39.009500Z

in your example, grandparent is a core.logic goal, not a pldb fact, so you cannot use it like that

2018-10-28T21:40:01.010500Z

a core.logic goal is like a query you can run over facts, in this case grandparent is a query you can run over a database of parent relationships to derive grandparent relationships

2018-10-28T21:43:59.012Z

Ok, but given these are relational operators, is there no way that I can take the statement [grandparent :Bob :John] and derive that that means => [parent :Bob _] [parent _ :John]?

2018-10-28T21:44:32.012400Z

It’s very likely that I’m formulating these incorrectly.

2018-10-28T21:45:13.013Z

Basically I’m trying to understand how I can create new facts, from statements.

2018-10-28T21:45:33.013200Z

Or is that just not possible?

2018-10-28T21:46:39.013700Z

Do I need to work out how to define grandparent as a db-rel perhaps?

2018-10-28T21:54:23.014800Z

you are looking to infer new facts based on existing facts and definitions of relationships between facts

2018-10-28T21:56:57.017Z

you have sort of half that, the missing half is you have to write something that runs the grandparents (rewritten to return some kind of inferred list of parent facts) and adds the results to the database

2018-10-28T21:57:21.017400Z

you might want something more like a rules engine, like clara

2018-10-28T21:57:43.017600Z

http://www.clara-rules.org/

2018-10-28T21:58:59.018300Z

clara has a fairly active slack channel if it does look like what you want #clara

2018-10-28T21:59:59.019700Z

but I dunno, maybe not, because rules engines generally don't have logic variables

2018-10-28T22:00:53.021Z

so [parent :Bob ?x] [parent ?x :John] isn't going to be directly something you can assert in to it

2018-10-28T22:02:47.022400Z

on the other hand, given the definition of grandparent, by construction if grandparent is true then we know [parent :Bob ?x] [parent ?x :John] is already true in the database, so there is no point in asserting it

2018-10-28T22:03:28.022800Z

Thanks for mentioning clara =)…

2018-10-28T22:04:08.023400Z

I’m still going through the Reasoned Schemer at the moment, so I’m going to keep reading that and banging my head against this for at least the next week or so and see if I can get somewhere and if that completely fails I’ll give it a look. Much appreciate your help though :)…

2018-10-28T23:39:37.024300Z

Also just out of curiosity, is there a reason that a lot of the examples I see use symbols? Instead of say keywords?

2018-10-28T23:40:15.024800Z

I just got bitten by this:

(l/run* [q]
  (l/== 
    '((pea)  pod)
    `((pea) ~q)))
=> ()
(l/run* [q]
  (l/== 
    '(pea  pod)
    `(pea ~q)))
=> ()
(l/run* [q]
  (l/== 
    '(:pea  :pod)
    `(:pea ~q)))
=> (:pod)

2018-10-28T23:41:15.025800Z

Finally realised it’s because in clojure the “`” resolves the symbol to the namespace, so the two symbols aren’t equal.

2018-10-30T13:49:22.032600Z

FYI the clojure syntax to unqualify a symbol during a is to use ~'foo`

2018-10-30T13:51:50.032900Z

I’m assuming by examples you mean minikanren/TRS examples, that you’re porting to clojure rather than core.logic ones