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.

Était-ce utile?

La 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.

Autres conseils

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))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top