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…you can't really call things in core.logic like that
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
I haven't really used pldb, but my guess is to create facts you call the name of the relation as a function
(parent :Bob :Mike)
not [parent :Bob :Mike]
but I might be wrong there
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
in your example, grandparent is a core.logic goal, not a pldb fact, so you cannot use it like that
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
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]
?
It’s very likely that I’m formulating these incorrectly.
Basically I’m trying to understand how I can create new facts, from statements.
Or is that just not possible?
Do I need to work out how to define grandparent
as a db-rel
perhaps?
you are looking to infer new facts based on existing facts and definitions of relationships between facts
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
you might want something more like a rules engine, like clara
clara has a fairly active slack channel if it does look like what you want #clara
but I dunno, maybe not, because rules engines generally don't have logic variables
so [parent :Bob ?x] [parent ?x :John] isn't going to be directly something you can assert in to it
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
Thanks for mentioning clara =)…
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 :)…
Also just out of curiosity, is there a reason that a lot of the examples I see use symbols? Instead of say keywords?
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)
Finally realised it’s because in clojure the “`” resolves the symbol to the namespace, so the two symbols aren’t equal.
FYI the clojure syntax to unqualify a symbol during a
is to use
~'foo`
I’m assuming by examples you mean minikanren/TRS examples, that you’re porting to clojure rather than core.logic
ones