Question

I'm sure this must be a stupid question, but how do I deal with a list of goals in core.logic?

(run* [g]
   (f))

(defn f[]
  '(succeed succeed)) 

Will throw an exception, as run* doesn't expect a list. I feel like I need to do (apply all (f)), but all is a macro, so that doesn't work.

What's the solution? I feel I'm missing something trivially obvious here...

Adrian.

Was it helpful?

Solution

If your goals take only one parameter then you can use everyg as suggested in another answer. Basically (everyg g coll) is a goal that succeeds when the goal g succeeds on each element of coll. Therefore coll is not a collection of goal, but a collection of single parameter to g. This still helps because, combined with project, this makes it possible to write:

(defn applyg
  [g v]
  "Goal that succeeds when the goal g applied to v succeeds.
  Non-relational as g must be ground."
  (project [g] (everyg g [v])))

And when there is a collection of goals to apply:

(defna apply-collg
  [gcoll v]
  ([() _])
  ([[gh . gt] _] (applyg gh v) (apply-collg gt v)))

Using pred to make a goal out of a clojure predicate, it becomes easy to test:

(run* [q] (apply-collg [#(pred % pos?) #(pred % odd?)] 1))
=> (_0)
(run* [q] (apply-collg [#(pred % pos?) #(pred % odd?)] 2))
=> ()

If the goals to apply take 2 or more parameters then one just need to transform them into goals taking a single collection of parameters.

I'm still quite new to core.logic so comments are welcomed.

OTHER TIPS

This seems to work:

(everyg succeed (f))

I'm still interested if there is a better or at least more idiomatic solution.

I haven't tried this, but looking at http://www.clojure.net/2012/10/02/More-core.logic/ there seems to be a similar thing using this construct:

(def f (all
         succeed
         succeed))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top