1

In core.logic, is there a way to translate the outputs of a program like

(run 2 [q]
  (fresh [a]
    (featurec q {:foo a})
    (membero a '(5))
    (conde 
      ((featurec q {:bar 2}))
      ((featurec q {:baz 2})))))

into the smallest maps that satisfy each solution's constraints, in this case {:foo 5, :bar 2} and {:foo 5, :baz 2}?

Alex Lew
  • 2,064
  • 14
  • 17
  • Why use `featurec` when the minimal set of keys is already known? Why not `(== q {:foo a :bar 2})`? – Taylor Wood Sep 25 '18 at 14:42
  • In a more complex (potentially even recursive) relation, some `featurec` clauses might appear only in some solutions; e.g., `conde` clauses that each introduce different `featurec` constraints. I've updated the question to give an example of this. – Alex Lew Sep 25 '18 at 15:52

1 Answers1

0

You could try this, which is a bit complicated, but it does the job.

(->> (run 1 [q]
              (fresh [l1 l2 a]
                     (membero a '(5))
                     (emptyo l1)
                     (conso [:foo a] l1 l2)
                     (conso [:bar 2] l2 q)))
         (first)
         (into {}))

or

(run 1 [q]
         (fresh [a B]
                (membero a '(5))
                (== B 2)
                (== q {:foo a :bar B})))

I am sure that William Byrd can do better.

akond
  • 15,865
  • 4
  • 35
  • 55
  • Thanks! The problem with (1) is that when `q` _is_ known, I want to be able to run this to pull out & constrain the relevant fields from `q` without worrying about the order in which `q` stores them (hence the map, rather than vector); and unfortunately, (2) wouldn't let me build up `featurec` constraints throughout a relation, potentially with `conde`s blocking some of them. – Alex Lew Sep 25 '18 at 15:52