<< Back to previous view

[LOGIC-153] deftest test-34-unify-with-metadata appears incorrect Created: 23/Dec/13  Updated: 01/Jan/14

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Andy Fingerhut Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   
(deftest test-34-unify-with-metadata
  (is (run* [q]
            (== q (quote ^:haz-meta-daytuhs (form form form))))
      '((^:haz-meta-daytuhs (form form form)))))

I am not sure what was intended for this, but replacing it with the following causes the test to fail.

(deftest test-34-unify-with-metadata
  (is (= (run* [q]
               (== q (quote ^:haz-meta-daytuhs (form form form))))
         '((^:haz-meta-daytuhs (form form form))))))

I think the correct version is probably close to that, though.



 Comments   
Comment by David Nolen [ 30/Dec/13 7:20 PM ]

I'm pretty sure meta data on forms caused exceptions and that's what this test was for.

Comment by Andy Fingerhut [ 01/Jan/14 12:05 PM ]

As that test is written now, it is of the form:

(is (run* [q] (expr))
    '(expr2))

The second argument to the macro 'is' is optional, and if present should be a string, not something like '(expr2). The test passes if (run* [q] (expr)) returns true without throwing an exception, and '(expr2) is ignored completely. That is why the test appears to be written incorrectly.





[LOGIC-146] run macro should take * in addition to n Created: 26/Nov/13  Updated: 16/Oct/14

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None





[LOGIC-141] dcg: def--> ClassCastException Created: 23/Aug/13  Updated: 23/Aug/13

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Greg Chapman Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I believe def--> needs to put its lsyms into a vector (as does -->). lsyms is passed to handle-clauses (as the env param), and there is used as a function. This causes an exception since a seq cannot be cast to a function.






[LOGIC-138] Allow tying multiple noms in one binder Created: 10/Jun/13  Updated: 10/Jun/13

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Tom Jack Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: nominal


 Description   

I think it may be useful to be able to tie multiple noms in one binder, with or without significant order.

A couple use cases I've thought of so far:

Lambdas in a non-currying language. Here order matters.

(== (list 'fn (ties [x y] (list '+ x y)))
    (list 'fn (ties [z w] (list '+ z w)))

My original use case, free/quantified variables in logical formulas. Order doesn't matter (note the second body has its noms swapped).

(== (list '∀ (ties #{x y} (list '= (list '+ x y) (list '+ y x))))
    (list '∀ (ties #{z w} (list '= (list '+ w z) (list '+ z w)))))

I have a draft implementation here: https://github.com/tomjack/core.logic/compare/ties

Possible issues with this implementation:

  • Is it OK to reextend IWalkTerm to IPersistentSet?
  • Should Tie and Ties present a uniform interface? (e.g. (tie? (ties #{x} x)))


 Comments   
Comment by David Nolen [ 10/Jun/13 3:37 PM ]

I really don't think the set bit is necessary, the vector syntax is fine. Also avoid needing to bring IWalkTerm back for sets. And yes, tie? should work in either case.

Comment by Tom Jack [ 10/Jun/13 3:55 PM ]

Hmm.. should:

(== (list 'fn (ties [x y] (list '- x y)))
    (list 'fn (ties [z w] (list '- w z)))

I'd think not.

Do you mean that order should always matter (take out the permutations stuff), or that it should never matter (don't use ties for cases like the above)?

Comment by David Nolen [ 10/Jun/13 4:07 PM ]

Ah hm, good point. Will think on it some more.





[LOGIC-130] StackOverFlowError when walking over set Created: 16/Apr/13  Updated: 16/Apr/13

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Coen De Roover Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None
Environment:

core.logic 0.8.3
Clojure 1.5



 Description   

Walking a Clojure set seems to cause a StackOverFlowError:

(run* [?s] (== ?s #{1 2 3}))

(let [s #{1 2 3}] (run* [?s] (== ?s s)))

(run* [?convertedseq ?seq] 
  (== ?seq #{1 2 3})
  (project [?seq]
    (== ?convertedseq (vector ?seq))))
StackOverflowError 
	clojure.core.logic/walk*/fn--2722 (logic.clj:216)
	clojure.core.logic/eval2927/fn--2928 (logic.clj:956)
	clojure.core.logic.protocols/eval1478/fn--1479/G--1469--1486 (protocols.clj:55)
	clojure.core.logic/walk* (logic.clj:214)
	clojure.core.logic/walk*/fn--2722 (logic.clj:218)
	clojure.core.logic/eval2927/fn--2928 (logic.clj:956)
	clojure.core.logic.protocols/eval1478/fn--1479/G--1469--1486 (protocols.clj:55)
	clojure.core.logic/walk* (logic.clj:214)
	clojure.core.logic/walk*/fn--2722 (logic.clj:218)
	clojure.core.logic/eval2927/fn--2928 (logic.clj:956)
	clojure.core.logic.protocols/eval1478/fn--1479/G--1469--1486 (protocols.clj:55)
	clojure.core.logic/walk* (logic.clj:214)


 Comments   
Comment by David Nolen [ 16/Apr/13 5:28 PM ]

core.logic no longer supports unification of sets so you're just seeing an error as result of a complete lack of support. I'm not against supporting basic unification of completely grounded sets, as then we only need to test for equality, but I'm inclined to make the system throw if any logic vars appear in the sets.





[LOGIC-128] add mod/rem/abs/min/max Created: 02/Apr/13  Updated: 15/Oct/14

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

SWI-Prolog's CLP(FD) module has this functionality http://www.swi-prolog.org/man/clpfd.html






[LOGIC-123] Allow unification with sequential in both directions Created: 23/Mar/13  Updated: 26/Mar/13

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Mike Anderson Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Currently I can't find a way to enable a custom data type to do unification with sequential objects in both direction. You can use IUnifyTerms to make it work in one direction, but it isn't possible to make it work in the other direction (i.e. when the sequential object is first).

The problem seemes to be in the following code:

(defn unify-with-sequential* [u v s]
  (cond
    (sequential? v)
    (if (and (counted? u) (counted? v)
          (not= (count u) (count v)))
      nil
      (loop [u u v v s s]
        (if (seq u)
          (if (seq v)
            (if-let [s (unify s (first u) (first v))]
              (recur (next u) (next v) s)
              nil)
            nil)
          (if (seq v) nil s))))
    
    (lcons? v) (unify-terms v u s)
    :else nil))

If the final nil could be replaced with a call to a protocol (IUnifyTermsReversed ???IUnifyWithSequential ???) then I believe it would make this extensible.



 Comments   
Comment by David Nolen [ 23/Mar/13 9:53 PM ]

I'm assume it's undesirable for your datatype to implement ISequential?

Comment by Mike Anderson [ 23/Mar/13 11:06 PM ]

It's undesirable because an expression can be a leaf node as well:

(+ 3 X) ;; OK as sequential
7 ;; definitely not sequential!

Hence making Expression implement ISequential would be problematic and break all kinds of contracts.....

Trying to unify the leaf node with a sequential object should fail of course, but that's logic I need to implement myself (I think??)

Comment by David Nolen [ 24/Mar/13 12:11 PM ]

I'm still not following as there's some context about your use case that I'm missing. Do you have a concrete core.logic example that you should think should work?

Comment by Mike Anderson [ 25/Mar/13 2:21 AM ]

Sure, here is my test case:

(let [ex1 (ex [+ 1 X])]  ;; an expression containing (+ 1 X) 
  (is (= [(ex X)] (run* [q] (fresh [op p] (== [op p q] ex1)))))  ;; fails
  (is (= [(ex X)] (run* [q] (fresh [op p] (== ex1 [op p q])))))  ;; OK
)

The first case fails (because of unify-with-sequential* returning nil as above). The second case is OK because it goes through my own implementation of IUnifyTerms. I may be wrong, but I don't think I can make it work without a change in core.logic itself.

Comment by David Nolen [ 25/Mar/13 7:39 AM ]

We used to support unifying in both directions but it made for a large number of protocols that had to be implemented. Recently I've been thinking it may be useful to provide coercion protocols, something like ICoerceToSequential.

Comment by Mike Anderson [ 25/Mar/13 7:37 PM ]

I think it is necessary to be able to support unifying in both directions somehow if custom data structures are ever going to be first-class citizens in core.logic?

I see how you could achieve this with ICoerceToSequential however so that might be a good solution. We do something a bit similar in core.matrix (to handle coercions between different back-end matrix implementations).

Comment by David Nolen [ 25/Mar/13 7:44 PM ]

custom data structures are already first class. Whether we should allow overloading unification of custom types with core Clojure interfaces/protocols/types is another matter entirely.

And sorry for the confusion. It's not clear to me why you want sequential to work, from your examples it appears that you have a proper expression type, what advantage is there for you to unify with sequential?

Comment by Mike Anderson [ 26/Mar/13 1:07 AM ]

I think it may be important if you have "sequence-like" data structures that aren't precisely sequential? but are conceptually equivalent to sequences. My custom Expression type is one example, and for interop reasons things like java.util.ArrayList spring to mind.

As it happens, I've switched back to using regular lists for the moment so the issue isn't a blocker for me. But it may still be worth thinking about.

Couple of advantages of doing this kind of unification would appear to be:
a) notational - you can use regular Clojure lists and vectors for unifying with something sequence-like
b) efficiency - avoid constructing a new custom object when it isn't needed (though the cost is probably too trivial to bother about in most cases....)

Of course, you may decide it is simpler and purer to avoid these complications, which is fine. But it seems a shame to have all the nice extensible protocols, and not quite be able to fully extend the functionality to custom types....





[LOGIC-89] Allow application again in pattern matches Created: 01/Jan/13  Updated: 15/Oct/14

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: 0.8.0


 Description   

Perhaps we can support simple function application in the following manner.

(defne substo [e new a out]
  (['(var ~a) _ _ new])
  (['(var ~y) _ _ '(var ~y)] (nom/hash a y))
  (['(app ~rator ~rand) _ _ '(app ~rator-res ~rand-res)]
     (substo rator new a rator-res)
     (substo rand new a rand-res))
  (['(lam ~(nom/tie c body)) _ _ '(lam ~(nom/tie c body-res))]
     (nom/hash c a) (nom/hash c new)
     (substo body new a body-res)))

If we have a seq in an unquote then we know we have an application. All function symbols are left alone, all arguments are considered to be fresh vars or locals.






[LOGIC-87] Decomplect the narrowing of the constraint space from the search order Created: 27/Dec/12  Updated: 28/Dec/12

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Jamie Brandon Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File flexible_search.patch    
Patch: Code and Test

 Description   

From a high-level point of view a constraint solver takes a constraint space, generates a tree of narrowings of the space and runs some search algorithm on the tree. Core.logic complects the generation of this tree and the search algorithm by representing the search space as a lazy stream of the leaves of the tree. By explicitly representing the search tree we get new search algorithms, optional fair conjunction and parallel search via fork-join.

More detail: http://scattered-thoughts.net/blog/2012/12/19/search-trees-and-core-dot-logic/

Github fork: https://github.com/clojure/core.logic/pull/13

Attached is a cleaned-up patch against d68e3400472c5f745e4c13d64433459e11ba4871



 Comments   
Comment by David Nolen [ 28/Dec/12 12:41 AM ]

Thanks! Will try to find some time this weekend to do a thorough review.





[LOGIC-86] make `defc` more useful Created: 26/Dec/12  Updated: 17/Mar/13

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

As we start adding more constraints it's becoming clear we really want to have to specify less boiler plate. Instead of:

(defn -treec
  ([x fc cform] (-treec x fc cform nil))
  ([x fc cform _id]
     (reify
       clojure.lang.IFn
       (invoke [this a]
         (let [x (walk a x)]
           (if (tree-term? x)
             ((composeg
               (constrain-tree x
                 (fn [t a] ((treec t fc cform) a)))
               (remcg this)) a)
             ((composeg
               (fc x)
               (remcg this)) a))))
       IConstraintId
       (id [this] _id)
       IWithConstraintId
       (with-id [this _id]
         (-treec x fc cform _id))
       IConstraintOp
       (rator [_] `treec)
       (rands [_] [x])
       IReifiableConstraint
       (reifyc [_ v r a]
         (let [x (walk* r x)]
           `(treec ~x ~cform)))
       IRelevant
       (-relevant? [_ a] true)
       IRunnable
       (runnable? [_ a]
         (not (lvar? (walk a x))))
       IConstraintWatchedStores
       (watched-stores [this] #{::subst}))))

(defn treec [x fc cform]
  (cgoal (-treec x fc cform)))

We should be able to write just:

(defc treec [x fc cform]
  clojure.lang.IFn
  (invoke [this a]
    (let [x (walk a x)]
      (if (tree-term? x)
        ((composeg
          (constrain-tree x
            (fn [t a] ((treec t fc cform) a)))
          (remcg this)) a)
        ((composeg
          (fc x)
          (remcg this)) a))))
  IConstraintRands
  (rands [_] [x])
  IReifiableConstraint
  (reifyc [_ v r a]
    (let [x (walk* r x)]
      `(treec ~x ~cform))))

`defc` should intelligently fill in the details.






[LOGIC-70] support for defaults in the simple unifier Created: 19/Nov/12  Updated: 17/Mar/13

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

There should be a way to specify a logic var with default values. If it is not unified with something it should unify with the default provided value.






[LOGIC-68] add Prolog meta-logical predicates bagof, setof, findall Created: 16/Nov/12  Updated: 15/Oct/14

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File 0001-LOGIC-68-Add-run-a-run-a-logic-functions-to-support-.patch    

 Description   

This can be done by annotating logic variables and embedding a run within a run by passing in the current substitution, running on it, and extracting out the reified values and unifying it back into the current substitution.



 Comments   
Comment by Aaron Brooks [ 16/Nov/12 1:23 PM ]

I'm working on understanding the answers given for this StackOverflow question:

http://stackoverflow.com/questions/7647758/prolog-findall-implementation

Comment by Aaron Brooks [ 16/Nov/12 10:02 PM ]

For discussion — Initial working patch supporting nested version of 'run-a/'run-a*. Binding symbols must match existing lvars with which vectors of all returned values will be unified.

Comment by Aaron Brooks [ 17/Nov/12 4:07 PM ]

Should we provide wrappers that emulate each of bagof, setof and findall?

I'm still not sold on the current names run-a/run-a*. "a" is really an internal implementation detail. Expect a revised patch with better names when I think of them (any ideas?).

Comment by David Nolen [ 17/Nov/12 8:32 PM ]

Yes please. Yeah I don't think the names of run-a/etc are critical - implementation details for now until we really understand the implications and it gets some use.

Comment by Aaron Brooks [ 21/Nov/12 10:51 AM ]

I'm considering simply making run/run* conditionalized on the first argument, using the nesting form if we are being called with a substitution map as the first argument.

My current understanding of bagof and findall makes me think they're not worth implementing beyond the nesting run functionality.

I'm still thinking about setof which is quite useful and will want help from the infrastructure to be fully efficient.

I'll submit a new patch after Thanksgiving.

Comment by David Nolen [ 21/Nov/12 10:57 AM ]

Excellent, thanks much.

Comment by Aaron Brooks [ 06/Dec/12 12:30 AM ]

I have not forgotten, I've just gotten swamped.

There's a small chance I'll get to this before Christmas, otherwise, it's after the new year.

Comment by Aaron Brooks [ 04/Feb/13 5:50 PM ]

After a car accident, travel to London and Morocco, getting caught up at work and getting caught up on the apparently very busy stream of core.logic activity (great work!), I'm back on this.

I found some bugs in my implementation after porting the patch forwards and realized these issues highlighted my sloppy understanding of some of the semantics I had created.

I'm fairly convinced now that we don't want to name this after run or run*. It's too much of a strain to try to make it mean the same thing in a nested context.

The current mechanism is still not quite a match for findall/bagof/setof, however, so I'm seeing what a good fit would be. I'll post meaningful thoughts for review as I have them.

Comment by David Nolen [ 13/Feb/13 1:50 PM ]

Glad to hear you're OK! No worries, will take a patch whenever you get around to one.

Comment by Aaron Brooks [ 12/Jun/13 9:03 PM ]

Having switched to Datomic which has bagof/setof type aggregation and subqueries (though the switch wasn't for those specifically) I don't know if or when I'll get back to this. Sorry!

Comment by David Nolen [ 13/Jun/13 1:36 AM ]

No worries! Glad Datomic is working out for you





[LOGIC-48] fd/in should provide a default domain if none specified Created: 30/Aug/12  Updated: 17/May/13

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

This domain should probably be (interval 0 Long/MAX_VALUE). In order for this to work this means we should probably accept passing in the vars to assigned domains as a seqable. It would be easy to accept the current way and this new way since if the first arg is not a symbol then the new behavior is being requested.

(fd/in [x y])
(fd/in [x y z] (interval 0 10))





[LOGIC-47] is macro needs to be improved Created: 30/Aug/12  Updated: 15/Oct/14

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

the is macro should work like the following:

(is x (- (+ a b) c))

All locals appearing in the right expression should be walked.






[LOGIC-44] ex* could expand macros in patterns Created: 19/Jul/12  Updated: 17/Mar/13

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Joe Osborn Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: enhancement, patch, test

Attachments: Text File exstar-macros.patch    
Patch: Code and Test

 Description   

So, tagged data structures are probably interesting in a relational context. Say you have a relation with some default logic about dogs:

(defna friendlyo [Dog-Or-Breed]
    ([:Spot] succeed)
    ([:Spike] fail)
    ([Other-Dog] (fresh [Breed] (dog-breed Other-Dog Breed) (friendlyo Breed)))
    ([(breed :miniature-dachshund)] fail)
    ([(breed :golden-retriever)] succeed)
    ;. . .)

Assume there's a (defmacro breed [t] `[:breed ~t]).

That's nicer than having to drop [:breed :golden-retriever] in there or whatever, since it's compile-time-checkable, less error-prone, reduces duplication, etc.

This little patch makes ex* expand macros in patterns so it doesn't treat e.g. (breed :golden-retriever) as introducing a new LVar called "breed". Test also provided.



 Comments   
Comment by David Nolen [ 19/Jul/12 4:41 PM ]

I'm surprised that this doesn't already work. We have support for unifying expressions in the pattern already. Look at line 1230 in tests.clj in the master branch.

So this should just work, no need to explicitly support macros as far as I can tell. If it's not working, then there's a bug.

Comment by Joe Osborn [ 19/Jul/12 5:18 PM ]

At least on 0.7.5, matching against a macro gives a runtime error:

Exception in thread "main" java.lang.ClassCastException: clojure.core.logic.LVar cannot be cast to clojure.lang.IFn
	at rl.core$glyph_$fn__123$fn__144$fn__165$fn__166$_inc__167$fn__168.invoke(core.clj:61)
	at clojure.core.logic.Substitutions.bind(logic.clj:211)
	at rl.core$glyph_$fn__123$fn__144$fn__165$fn__166$_inc__167.invoke(core.clj:58)
	at clojure.core.logic$fn__1056$_inc__1057.invoke(logic.clj:1160)
	at clojure.core.logic$fn__1056$_inc__1057.invoke(logic.clj:1160)
	at clojure.core.logic$fn__898$_inc__899.invoke(logic.clj:823)
	at clojure.core.logic$fn__890$fn__891.invoke(logic.clj:828)

Using a fn instead of a macro gives the same:

Exception in thread "main" java.lang.ClassCastException: clojure.core.logic.LVar cannot be cast to clojure.lang.IFn
	at rl.core$drawable_$fn__235$fn__248$fn__249$_inc__250$fn__251.invoke(core.clj:67)
	at clojure.core.logic.Substitutions.bind(logic.clj:211)
	at rl.core$drawable_$fn__235$fn__248$fn__249$_inc__250.invoke(core.clj:65)
	at clojure.core.logic$fn__1056$_inc__1057.invoke(logic.clj:1160)
	at clojure.core.logic$fn__894$_inc__895.invoke(logic.clj:826)
	at clojure.core.logic$fn__1056$_inc__1057.invoke(logic.clj:1160)
	at clojure.core.logic$fn__898$_inc__899.invoke(logic.clj:823)
	at clojure.core.logic$fn__898$_inc__899.invoke(logic.clj:823)
	at clojure.core.logic$fn__898$_inc__899.invoke(logic.clj:823)
	at clojure.core.logic$fn__890$fn__891.invoke(logic.clj:828)

Here's (glyph-) for reference (don't mind all the extra [], I have a weird key/value thing because of some conveniences for maintaining fact identity in a temporal database):

(defna glyph- [Key Val]
	([[Thing] [Glyph]] (thing- [Thing]) (on-fire_ *turn* [Thing]) (== Glyph \δ))
	([[Thing] [Glyph]] (thing- [Thing]) (fresh [Type] (type- [Thing] [Type]) (glyph- [Type] [Glyph])))
	([[(type-enum :player)] [Glyph]] (== Glyph \@))
	([[(type-enum :dragon)] [Glyph]] (== Glyph \D))
	([[Type] [Glyph]] (== Glyph \?)))

and type-enum as a macro:

(defmacro type-enum [v] `[:enum :type ~v])

and as a fn:

(defn type-enum [v] [:enum :type ~v])

I'll mess around and see if my example works in HEAD.

Comment by Joe Osborn [ 19/Jul/12 5:37 PM ]

Same exception with this test case in HEAD (sorry for all the facts):

(defrel thing- [Thing])
(defrel type- [Thing] [Type])
(fact thing- [0])
(fact thing- [1])
(fact thing- [2])
(fact type- [0] [:player])
(fact type- [1] [:dragon])
(fact type- [2] [:pig])
(defn type-enum [t] [:type t])
(defna drawable- [Key]
  ([[Thing]] (thing- [Thing]) (fresh [Type] (type- [Thing] [Type]) (drawable- [Type])))
  ([[(type-enum :player)]] succeed)
  ([[(type-enum :dragon)]] succeed))

(deftest do-fns-work
	(is (= (run* [q] (drawable- [q])) '(0 1))))

Now that I look at it, I may be expecting a wrong-format return value, but the point is that I don't even get that far.

Using the REPL, I checked out how (defna drawable- . . .) expands (tidied up slightly):

(def drawable- (clojure.core/fn ([Key] 
  (clojure.core.logic/conda 
	  ((clojure.core.logic/fresh [Thing] (clojure.core.logic/== [Thing] Key) (thing- [Thing]) (fresh [Type] (type- [Thing] [Type]) (drawable- [Type])))) 
		((clojure.core.logic/fresh [type-enum] 
		  (clojure.core.logic/== [(type-enum :player)] Key) succeed))
		((clojure.core.logic/fresh [type-enum] 
		  (clojure.core.logic/== [(type-enum :dragon)] Key) succeed))))))

Note the (clojure.core.logic/fresh [type-enum] . . .) forms, which are exactly what I would not want to see in this case.

I'm not really sure why this doesn't work here yet works for the matche test case.

Comment by David Nolen [ 19/Jul/12 5:47 PM ]
[(type-enum :dragon)]

This pattern make it seem like you want to match:

[[:type :dragon]]

Note extra level of brackets here. Is this the case?

Even so I agree that the expansion doesn't look quite right. We should never descend into a seq form like that.

Comment by Joe Osborn [ 19/Jul/12 5:57 PM ]

Yes, that's exactly the desired outcome in this case--a tagged value in my naive interpretation. Is the reason it fails whereas the test on :1230 doesn't the fact that it's producing a vector and not a list? Changing the fn to return a list instead of a vector didn't seem to help.

My patch, fwiw, doesn't exhibit that behavior (at least for macros, haven't tested it with fns).

Comment by David Nolen [ 19/Jul/12 9:11 PM ]

What I mean is don't you want the following instead?

(defna drawable- [Key]
  ([[Thing]] (thing- [Thing]) (fresh [Type] (type- [Thing] [Type]) (drawable- [Type])))
  ([(type-enum :player)] succeed)
  ([(type-enum :dragon)] succeed))

Note that I removed a layer of square brackets.

Comment by Joe Osborn [ 20/Jul/12 10:28 AM ]

Nope! I actually want both. I'm doing some temporal logic stuff and I wanted some conveniences for "updating" a fluent, so I wanted to distinguish between the "key part" and the "value part" of the arguments. It looks silly for facts with no "value part", but it lets me write procedures and fns something like this:

(defrel heldo Time Fluent)
(defrel ¬heldo Time Fluent)
(declare fluent-obtainedo) ; most recent 'held' not terminated by a '¬held', or fail
(defn alter-fluent [Time Rel Key NewVal]
  ;todo: error check, ensure old != new, old obtains, new does not obtain
  (doseq [old-val (run* [old-val] (fluent-obtainedo Time [Rel Key old-val]))]
    (fact ¬heldo Time [Rel Key old-val]))
  (fact heldo Time [Rel Key NewVal]))
. . .
(fact heldo 0 ['pos [0] [0 0]])
. . .
(alter-fluent 1 'pos [0] [1 1])

And I write all the non-temporal fluents that way too for consistency and to help prevent mistakes.

Comment by David Nolen [ 20/Jul/12 2:58 PM ]

I'll try to give a closer look at this issue over the weekend.

Comment by David Nolen [ 17/Mar/13 7:05 PM ]

We're thinking about a more general solution here: http://github.com/clojure/core.logic/wiki/Better-syntax-support





[LOGIC-43] LVar should print readably Created: 05/Jul/12  Updated: 05/Jul/12

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Alan Malloy Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File 0001-Make-lvar-print-readably.patch    
Patch: Code

 Description   

Currently LVar objects print the same as symbols; they should either print as an unreadable form, or in a way that the reader can read them back in and get an LVar. Attached patch causes them to be read in as LVars.

However, (read-string (pr-str lv)) does not compare as equal to lv, because the implementation of .equals relies on their string :name objects being identical? - which they will not be, if one LVar was created by the lvar function, which uses str, and the other created by read-string, which uses String/intern.

It seems plausible to say that LVars can't be compared for equality after sending them through strings, but that's awkward and unpleasant. We could instead define LVars to compare their names with = rather than with identical?, but David expressed concern about the performance implications of that change.






[LOGIC-38] Logic Threading Macro Created: 13/May/12  Updated: 15/Oct/14

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Jason Jackson Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File 0001-added-logic-threading-macro.patch     Text File 0001-added-logic-threading-macro.patch    

 Description   

This macro was somewhat useful when I was implementing static analysis for a compiler with core.logic.

(defmacro ==>> [expr-in & rel-forms]
"Thread the expr-in through rel-forms then unify with last rel-forms
(the 'out expression').

Example:
(==>> [[1]] (firsto) (firsto) x))
;; 'x' will become bound to value 1

This macro expands to:
(fresh [_A _B]
(firsto [[1]] _A)
(firsto _A _B)
(== _B q))

If you imagine that the 'return value' of firsto is its last parameter,
then it works just like clojure.core/-> as return value of each form is
first argument of the following form."



 Comments   
Comment by Jason Jackson [ 13/May/12 11:08 AM ]

There might be a better name, not sure.

Comment by Jason Jackson [ 13/May/12 11:18 AM ]

renamed ==>> to ==->





[LOGIC-35] Core.logic equivalent of multimethods Created: 02/Apr/12  Updated: 28/Dec/12

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Gabriel Pickard Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: enhancement


 Description   

I need to define predicates to which I can later (and from other namespaces) attach further clauses (so not just facts). I couldn't find any such functionality in the source. Due to the extensive use of macros, hacking such a system onto core.logic from the outside is extremely difficult, if not impossible (to me at least).

I'd love to implement this myself too, if given an OK and rough direction.



 Comments   
Comment by Gabriel Pickard [ 03/Apr/12 6:27 PM ]

I actually did manage to tack on a prototype that covers the basic behavior I would like to see: https://github.com/werg/herpderp/blob/master/src/herpderp/multo.clj

I use a set stored in a ref in the defne's metadata to manage dynamic changes to the clauses. Upon changing that set using defclause I use eval to re-define the var using defne.

This might not be nice, but allows me to continue developing features against it.

Comment by David Nolen [ 28/Dec/12 12:48 AM ]

I don't think the current implementation can really support this and I don't think it's wise to try to hack around the current implementation. I'd be willing to consider a comprehensive solution if someone is willing to do the legwork.





[LOGIC-28] defrel cannot be called inside function Created: 15/Feb/12  Updated: 17/Mar/13

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Jason Jackson Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File 0001-allow-defrel-to-be-called-from-within-a-function-if-.patch     File patch-defrel    

 Comments   
Comment by David Nolen [ 20/Feb/12 2:15 PM ]

Can you reformat the patch w/ git so it has the proper attribution information? Thanks!

Comment by Jason Jackson [ 13/May/12 10:06 AM ]

New patch with attribution info. Sorry about super long turn around time, in the future I should be much faster.

Comment by Martin Trojer [ 20/Sep/12 3:32 AM ]

This patch solved the exact same problem for me aswell.

Cheers...

Comment by David Nolen [ 20/Sep/12 10:57 AM ]

I've yet to hear a good rationale for this patch. defrel has the same semantics as def and should only exist at the top level. If someone puts more though into what defining a rel dynamically should look like I will consider it.

Comment by Jason Jackson [ 20/Sep/12 2:02 PM ]

I only implemented this so I could delete relation state. There's probably a better way to do this though.

Comment by Martin Trojer [ 21/Sep/12 2:47 AM ]

Indeed, a make-rel function would be optimal, then you can def it (or store it somewhere else) at your leisure.





[LOGIC-26] Generate a better error when adding facts for arities that do not exist Created: 23/Jan/12  Updated: 17/Mar/13

Status: Open
Project: core.logic
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None





Generated at Fri Oct 31 23:52:56 CDT 2014 using JIRA 4.4#649-r158309.