<< Back to previous view

[MATCH-36] throw on unsuccessful match Created: 27/Oct/11  Updated: 30/Nov/11

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

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


 Description   

I was on the fence about this. But after looking at the literature as well as the behavior of condp, I've decided that throwing on unsuccessful match is the way to go. This is particularly important since we put no constraints on the types allowed - we cannot determine exhaustiveness.






[MATCH-31] vector patterns should work on seq Created: 10/Oct/11  Updated: 30/Nov/11

Status: In Progress
Project: core.match
Component/s: None
Affects Version/s: None
Fix Version/s: None

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


 Description   

This means abandoning subvec and using nth + offsets.






[MATCH-47] vector patterns dispatch on count after dispatching on type Created: 23/Dec/11  Updated: 23/Dec/11

Status: In Progress
Project: core.match
Component/s: None
Affects Version/s: None
Fix Version/s: None

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


 Description   

The current behavior just creates complications.






[MATCH-35] Bug in seq pattern matching Created: 27/Oct/11  Updated: 11/Jan/12

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

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


 Description   
(let [l '(1 2 3)]
    (match [l]
      [([a & [b & [c d]]] :seq)] :a0
      :else :a1))

Matches when it shouldn't.



 Comments   
Comment by Greg Chapman [ 11/Jan/12 10:24 AM ]

Another example of (I think) the same issue:

user=> (let [x ()] (match [x] [([h & t] :seq)] [h t] [_] :a1))
[nil ()]

Perhaps SeqPattern's IPatternCompile should call seq in order to filter empty seqs? (e.g.:

(to-source* [this ocr]
`(and (or (seq? ~ocr) (sequential? ~ocr)) (seq ~ocr)))





[MATCH-4] Optimized pattern matching on deftype/record, POJOs Created: 04/Sep/11  Updated: 27/Oct/11

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

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


 Description   
(match [x]
  [({:a 0 :b 1} :type Foo)] :a0
  ...)

:a and :b would be converted to field access, i.e. (.a x)

As with primitive array matching, we should do an instance check followed by hinted field access.

We should consider adopting the deftype/record syntax.



 Comments   
Comment by David Nolen [ 27/Oct/11 4:41 PM ]
(match [x]
  [^Foo {.-bar 5 .-baz 7}] :a0
  [^Foo {.-bar _ .-woz 8}] :a1
  :else :a2)

Given the recent ClojureScript property access discussions this seems like an acceptable syntax for high-performance property access.

Maybe:

(match [^Foo x]
  [{.-bar 5 .-baz 7}] :a0
  [{.-bar _ .-woz 8}] :a1
  :else :a2)

But probably not since then we should probably throw if someone tries to declare a different type in the row.





[MATCH-2] Matching Diagnostics Created: 04/Sep/11  Updated: 27/Oct/11

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

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


 Description   

Communicate to the user precisely what failed to match. Conversation here: http://groups.google.com/group/clojure/browse_thread/thread/675456fba1712214. We adopt the behavior of condp since that is closer to what match does and will do (predicate dispatch)



 Comments   
Comment by David Nolen [ 05/Sep/11 10:40 AM ]

Continuing the conversation from GitHub - concerning your changes, we should probably show what current occurrence failed to match as well as the breadcrumb.

Comment by David Nolen [ 26/Sep/11 7:10 AM ]

Matching diagnostics will be complicated by MATCH-1. Clojure doesn't yet support simple data conveying exceptions. Will probably have to use a combination of proxy and definterface.

Comment by Ambrose Bonnaire-Sergeant [ 30/Sep/11 4:39 AM ]

I haven't yet kept up with your backtracking changes, and I just noticed this conversation, so I'll have to have another look at diagnostics with backtracking.





[MATCH-40] Allow or'ing of guard functions Created: 21/Nov/11  Updated: 21/Nov/11

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

Type: Enhancement Priority: Major
Reporter: Hugo Duncan Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

In order to simplify composition of guard predicates which are alternatives, allow for passing a sequence of predicates whose values when called will be or'd together.

The :when keyword currently allows passing of a vector of predicates that are and'd together.

Either case (`and` or `or`) can be achieved externally to match via composition, and an alternative might be to force explicit composition outside of core.match.

At the least, the documentation should mention that multiple predicates will be and'd together.






[MATCH-39] Allow matching of map expressions to restrict the set of keys present in the value to a subset of a specified set of keys Created: 21/Nov/11  Updated: 21/Nov/11

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

Type: Enhancement Priority: Major
Reporter: Hugo Duncan Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

It is useful, to be able to constrain a match on a map value to limit the set of keys present in the value, without enforcing that the keys are all present in the value.

The current :only option, enforces a strict matching of keys.

{{(let [x {:a 1} (match [x] [({:a _ :b _} :only [:a :b])])}} => doesn't match

This came up trying to write a precondition on the argument of a function, which allowed optional keys, but wanted to restrict the overall set of keys.



 Comments   
Comment by David Nolen [ 21/Nov/11 12:22 PM ]
(match x
  ({:c 1} :has [:a :b]) :a0
  ...)

or

(match x
  ({:c 1} :contains [:a :b]) :a0
  ...)

Seems reasonable.

Comment by David Nolen [ 21/Nov/11 12:34 PM ]

Ah misunderstood. You want something like :allowed.





[MATCH-55] Matching a sequence with just a rest pattern fails to compile Created: 21/Mar/12  Updated: 21/Mar/12

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

Type: Defect Priority: Major
Reporter: Hugo Duncan Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

In 0.2.0-alpha9,

(match [ [1 2] ] [([& _] :seq)] true)

fails to compile with No method in multimethod 'to-source' for dispatch value: class clojure.core.match.RestPattern






[MATCH-56] IndexOutOfBoundsException when matching empty vector Created: 27/Mar/12  Updated: 27/Mar/12

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

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

Clojure 1.3


Attachments: File match.clj.diff    

 Description   

Using the latest core.match:

user=> (let [x []] (match [x] [[h & t]] [h t] :else :nomatch))
IndexOutOfBoundsException clojure.lang.RT.subvec (RT.java:1451)

Not sure if this is the best fix, but I resolved this specific case by slightly changing subvec-inline (see attached diff).



 Comments   
Comment by David Nolen [ 27/Mar/12 10:28 AM ]

Thanks for the report. The patch is not going to work - we should be checking that the vector has at least one item.





[MATCH-58] we should test the presence of key with find, not get Created: 07/Apr/12  Updated: 07/Apr/12

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

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


 Description   

If a user really doesn't care about the existence of a key they won't match on it. The current behavior is very confusing.






[MATCH-61] Exception thrown when matching using :seq when there is a seq call in the tail of the occurrences Created: 22/Jun/12  Updated: 22/Jun/12

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

Type: Defect Priority: Major
Reporter: Emma Tosch Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: bug, seq
Environment:

with Clojure 1.3



 Description   

<iframe style="width: 648px; height: 400px; border: 0px;" src="http://refheap.com/paste/3294/framed" >

I also tested with three occurrences. When there is a seq call in the second occurrence onward a RuntimeException is thrown.



 Comments   
Comment by Emma Tosch [ 22/Jun/12 5:33 PM ]

https://gist.github.com/626088b01817ac638fae
Two expressions, macro-expanded. The only difference between the expressions is that the second occurrence in the second expression is seq'ed. The second let is the one throwing the exception; it's the one with the binding

(clojure.core/let [q_tail_3472 q_tail_3472
q_head_3471 q_head_3471
ocr-3470 (seq y)
z z]
...)





[MATCH-49] Duplicate wildcard detection in pattern row doesn't account for locals Created: 12/Jan/12  Updated: 12/Jan/12

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

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





[MATCH-64] Improve match compile times Created: 15/Aug/12  Updated: 15/Aug/12

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

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





[MATCH-65] cata matching Created: 23/Nov/12  Updated: 23/Nov/12

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

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


 Description   

Dan Friedman's pattern matcher has a nice feature called cata-matching - allowing recursive matching from the match itself. Useful when writing compilers.






[MATCH-63] IllegalArgumentException when AOT compiling namespace using clojure.core.match since alpha10 Created: 08/Aug/12  Updated: 26/Feb/13

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

Type: Defect Priority: Major
Reporter: Paudi Moriarty Assignee: David Nolen
Resolution: Unresolved Votes: 3
Labels: None
Environment:

core.match 0.2.0-alpha10 and 0.2.0-alpha11-SNAPSHOT (git 7ad66cc)
clojure 1.3.0 and 1.4.0


Attachments: Zip Archive matchtest.zip    

 Description   

Getting this when AOT compiling a trivial project (attached) using alpha10: (works fine with alpha9)

Caused by: java.lang.IllegalArgumentException: No method in multimethod 'to-source' for dispatch value: class clojure.core.match.WildcardPattern
	at clojure.lang.MultiFn.getFn(MultiFn.java:121)
	at clojure.lang.MultiFn.invoke(MultiFn.java:167)
	at clojure.core.match$dag_clause_to_clj.invoke(match.clj:424)
	at clojure.lang.AFn.applyToHelper(AFn.java:167)
	at clojure.lang.AFn.applyTo(AFn.java:151)
	at clojure.core$apply.invoke(core.clj:602)
	at clojure.lang.AFn.applyToHelper(AFn.java:167)
	at clojure.lang.RestFn.applyTo(RestFn.java:132)
	at clojure.core$apply.invoke(core.clj:604)
	at clojure.core$partial$fn__3796.doInvoke(core.clj:2343)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$map$fn__3811.invoke(core.clj:2430)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.RT.seq(RT.java:466)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core$apply.invoke(core.clj:600)
	at clojure.core$mapcat.doInvoke(core.clj:2459)
	at clojure.lang.RestFn.invoke(RestFn.java:423)
	at clojure.core.match.SwitchNode.n_to_clj(match.clj:446)
	at clojure.core.match.BindNode.n_to_clj(match.clj:411)
	at clojure.core.match$executable_form.invoke(match.clj:1713)
	at clojure.core.match$clj_form.invoke(match.clj:1721)
	at clojure.core.match$match.doInvoke(match.clj:1750)


 Comments   
Comment by Frederik De Bleser [ 20/Nov/12 4:18 PM ]

I can confirm the same issue on alpha11.

Comment by David Nolen [ 23/Nov/12 4:52 PM ]

I believe I may have found the cause and have fixed master - if someone can confirm I'll happily cut another release.

http://github.com/clojure/core.match/commit/cbcc6e5fa070a7025e72f5eab4e83eaec100332b

Comment by Paudi Moriarty [ 15/Jan/13 9:42 AM ]

Thanks David,

That change has not fixed the issue for me.

Comment by Paudi Moriarty [ 15/Jan/13 9:56 AM ]

So the pattern parameter being passed to dag-clause-to-clj:

(defn dag-clause-to-clj [occurrence pattern action]
  (let [test (if (instance? clojure.core.match.IPatternCompile pattern)
               (to-source* pattern occurrence)
               (to-source pattern occurrence))]
...

is a WildcardPattern which doesn't implement IPatternCompile and doesn't have a to-source method. So it seems it shouldn't be passed at all. Indeed, in normal usage it isn't.

;; ## Wildcard Pattern
;; 
;; A wildcard pattern accepts any value.
;;
;; In practice, the DAG compilation eliminates any wildcard patterns.

(defprotocol IWildcardPattern
  (sym [this]))

(deftype WildcardPattern [sym _meta]
  IWildcardPattern
  (sym [_] sym)
  clojure.lang.IObj
  (meta [_] _meta)
  (withMeta [_ new-meta]
    (WildcardPattern. sym new-meta))
  Object
  (toString [_]
    (str sym)))
Comment by David Nolen [ 15/Jan/13 11:17 AM ]

Can you include an example pattern which works under normal circumstances but fails under AOT? This must meant that WildcardPatterns are making it through under AOT and getting to the multimethod case but not under incremental compilation at the REPL.

Comment by Paudi Moriarty [ 16/Jan/13 9:34 AM ]

This seems to do it:

(match {}
  {:a :x :b b} :dummy
  :else :dummy)
Comment by Tim Olsen [ 26/Feb/13 1:55 PM ]

I've seen this problem as well. If I try to compile a second time, however, without running lein clean, the compilation succeeds. Maybe it's a bootstrapping problem?





[MATCH-69] AOT-compiling match expression produces stack overflow Created: 24/Apr/13  Updated: 24/Apr/13

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

Type: Defect Priority: Major
Reporter: Chas Emerick Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

The offending match expression is pretty gnarly, will try to simplify and post it here later. For now, a (partial) stack trace, eliding the repeating bits:

Caused by: java.lang.StackOverflowError
	at clojure.core$map$fn__4207.invoke(core.clj:2479)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.ChunkedCons.chunkedNext(ChunkedCons.java:59)
	at clojure.lang.ChunkedCons.next(ChunkedCons.java:43)
	at clojure.lang.PersistentVector.create(PersistentVector.java:51)
	at clojure.lang.LazilyPersistentVector.create(LazilyPersistentVector.java:31)
	at clojure.core$vec.invoke(core.clj:354)
	at clojure.core.match.PatternMatrix.column(match.clj:713)
	at clojure.core.match$useful_p_QMARK_.invoke(match.clj:811)
	at clojure.core.match.PatternMatrix$iter__1458__1464$fn__1465$iter__1460__1466$fn__1467$fn__1468.invoke(match.clj:765)
	at clojure.core.match.PatternMatrix$iter__1458__1464$fn__1465$iter__1460__1466$fn__1467.invoke(match.clj:763)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.RT.seq(RT.java:484)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core.match.PatternMatrix$iter__1458__1464$fn__1465.invoke(match.clj:764)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:67)
	at clojure.lang.RT.seq(RT.java:484)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core$partition$fn__4309.invoke(core.clj:2834)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.RT.seq(RT.java:484)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core$map$fn__4207.invoke(core.clj:2479)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.Cons.next(Cons.java:39)
	at clojure.lang.PersistentVector.create(PersistentVector.java:51)
	at clojure.lang.LazilyPersistentVector.create(LazilyPersistentVector.java:31)
	at clojure.core$vec.invoke(core.clj:354)
	at clojure.core.match.PatternMatrix.useful_matrix(match.clj:763)
	at clojure.core.match.PatternMatrix.necessary_column(match.clj:755)
	at clojure.core.match.PatternMatrix$choose_column__1441.invoke(match.clj:720)
	at clojure.core.match.PatternMatrix.compile(match.clj:738)
	at clojure.core.match$first_column_chosen_case$switch_clauses__1406$fn__1407.invoke(match.clj:643)
	at clojure.core$map$fn__4211.invoke(core.clj:2492)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.RT.seq(RT.java:484)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core.protocols$seq_reduce.invoke(protocols.clj:30)
	at clojure.core.protocols$fn__6026.invoke(protocols.clj:54)
	at clojure.core.protocols$fn__5979$G__5974__5992.invoke(protocols.clj:13)
	at clojure.core$reduce.invoke(core.clj:6177)
	at clojure.core$into.invoke(core.clj:6229)
	at clojure.core.match$first_column_chosen_case$switch_clauses__1406.invoke(match.clj:646)
	at clojure.core.match$first_column_chosen_case.invoke(match.clj:676)
	at clojure.core.match.PatternMatrix.compile(match.clj:740)
	at clojure.core.match$first_column_chosen_case$switch_clauses__1406$fn__1407.invoke(match.clj:643)
	at clojure.core$map$fn__4211.invoke(core.clj:2492)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.RT.seq(RT.java:484)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core.protocols$seq_reduce.invoke(protocols.clj:30)
	at clojure.core.protocols$fn__6026.invoke(protocols.clj:54)
	at clojure.core.protocols$fn__5979$G__5974__5992.invoke(protocols.clj:13)
	at clojure.core$reduce.invoke(core.clj:6177)
	at clojure.core$into.invoke(core.clj:6229)





[MATCH-54] Cannot AOT with certain match expression. Created: 04/Mar/12  Updated: 18/May/13

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

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


 Description   

If you try to AOT this code, you get an exception.

(defn -main [& args]
  (println args)
  (let [x nil] 
    (match x
      ["=" _ _] true
      [[:invoke _] _] true)))

Stack Trace:

Compiling foo.core
Exception in thread "main" java.lang.IndexOutOfBoundsException, compiling:(foo/core.clj:8)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6416)
	at clojure.lang.Compiler.analyze(Compiler.java:6216)
	at clojure.lang.Compiler.analyze(Compiler.java:6177)
	at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5572)
	at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5873)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6409)
	at clojure.lang.Compiler.analyze(Compiler.java:6216)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6397)
	at clojure.lang.Compiler.analyze(Compiler.java:6216)
	at clojure.lang.Compiler.analyze(Compiler.java:6177)
	at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5572)
	at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5008)
	at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3629)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6407)
	at clojure.lang.Compiler.analyze(Compiler.java:6216)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6397)
	at clojure.lang.Compiler.analyze(Compiler.java:6216)
	at clojure.lang.Compiler.access$100(Compiler.java:37)
	at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:492)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6409)
	at clojure.lang.Compiler.analyze(Compiler.java:6216)
	at clojure.lang.Compiler.analyze(Compiler.java:6177)
	at clojure.lang.Compiler.compile1(Compiler.java:6980)
	at clojure.lang.Compiler.compile(Compiler.java:7046)
	at clojure.lang.RT.compile(RT.java:385)
	at clojure.lang.RT.load(RT.java:425)
	at clojure.lang.RT.load(RT.java:398)
	at clojure.core$load$fn__4610.invoke(core.clj:5386)
	at clojure.core$load.doInvoke(core.clj:5385)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invoke(core.clj:5200)
	at clojure.core$compile$fn__4615.invoke(core.clj:5397)
	at clojure.core$compile.invoke(core.clj:5396)
	at user$eval27.invoke(NO_SOURCE_FILE:1)
	at clojure.lang.Compiler.eval(Compiler.java:6465)
	at clojure.lang.Compiler.eval(Compiler.java:6455)
	at clojure.lang.Compiler.eval(Compiler.java:6431)
	at clojure.core$eval.invoke(core.clj:2795)
	at clojure.main$eval_opt.invoke(main.clj:296)
	at clojure.main$initialize.invoke(main.clj:315)
	at clojure.main$null_opt.invoke(main.clj:348)
	at clojure.main$main.doInvoke(main.clj:426)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at clojure.lang.Var.invoke(Var.java:405)
	at clojure.lang.AFn.applyToHelper(AFn.java:163)
	at clojure.lang.Var.applyTo(Var.java:518)
	at clojure.main.main(main.java:37)
Caused by: java.lang.IndexOutOfBoundsException
	at clojure.lang.PersistentVector.arrayFor(PersistentVector.java:106)
	at clojure.lang.PersistentVector.nth(PersistentVector.java:110)
	at clojure.lang.RT.nth(RT.java:741)
	at clojure.core.match.PatternRow.invoke(match.clj:327)
	at clojure.core.match.PatternMatrix.pattern_at(match.clj:713)
	at clojure.core.match$useful_p_QMARK_.invoke(match.clj:778)
	at clojure.core.match.PatternMatrix$iter__832__838$fn__839$iter__834__840$fn__841$fn__842.invoke(match.clj:735)
	at clojure.core.match.PatternMatrix$iter__832__838$fn__839$iter__834__840$fn__841.invoke(match.clj:733)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.RT.seq(RT.java:466)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core.match.PatternMatrix$iter__832__838$fn__839.invoke(match.clj:734)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:67)
	at clojure.lang.RT.seq(RT.java:466)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core$partition$fn__3913.invoke(core.clj:2777)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.RT.seq(RT.java:466)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core$map$fn__3811.invoke(core.clj:2424)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.Cons.next(Cons.java:39)
	at clojure.lang.PersistentVector.create(PersistentVector.java:50)
	at clojure.lang.LazilyPersistentVector.create(LazilyPersistentVector.java:31)
	at clojure.core$vec.invoke(core.clj:345)
	at clojure.core.match.PatternMatrix.useful_matrix(match.clj:733)
	at clojure.core.match.PatternMatrix.necessary_column(match.clj:725)
	at clojure.core.match.PatternMatrix$choose_column__815.invoke(match.clj:690)
	at clojure.core.match.PatternMatrix.compile(match.clj:708)
	at clojure.core.match$first_column_chosen_case$switch_clauses__780$fn__781.invoke(match.clj:613)
	at clojure.core$map$fn__3815.invoke(core.clj:2437)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.RT.seq(RT.java:466)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core$reduce.invoke(core.clj:5994)
	at clojure.core$into.invoke(core.clj:6004)
	at clojure.core.match$first_column_chosen_case$switch_clauses__780.invoke(match.clj:616)
	at clojure.core.match$first_column_chosen_case.invoke(match.clj:646)
	at clojure.core.match.PatternMatrix.compile(match.clj:710)
	at clojure.core.match$first_column_chosen_case$switch_clauses__780$fn__781.invoke(match.clj:613)
	at clojure.core$map$fn__3815.invoke(core.clj:2437)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:60)
	at clojure.lang.RT.seq(RT.java:466)
	at clojure.core$seq.invoke(core.clj:133)
	at clojure.core$reduce.invoke(core.clj:5994)
	at clojure.core$into.invoke(core.clj:6004)
	at clojure.core.match$first_column_chosen_case$switch_clauses__780.invoke(match.clj:616)
	at clojure.core.match$first_column_chosen_case.invoke(match.clj:646)
	at clojure.core.match.PatternMatrix.compile(match.clj:710)
	at clojure.core.match$clj_form.invoke(match.clj:1616)
	at clojure.core.match$match.doInvoke(match.clj:1645)
	at clojure.lang.RestFn.invoke(RestFn.java:573)
	at clojure.lang.Var.invoke(Var.java:426)
	at clojure.lang.AFn.applyToHelper(AFn.java:193)
	at clojure.lang.Var.applyTo(Var.java:518)
	at clojure.lang.Compiler.macroexpand1(Compiler.java:6320)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6395)
	... 46 more





[MATCH-51] Fail to match empty vector Created: 21/Jan/12  Updated: 18/May/13

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

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


 Description   
(match (vector)
  ([(re :guard string?)] :seq) 4
  [] 6)

This should evaluate to 6 not nil.



 Comments   
Comment by Jason Jackson [ 21/Jan/12 9:30 AM ]

tested on 0.2.0-alpha10-SNAPSHOT





[MATCH-53] Match doesn't work when AOT compiled into a JAR, but manually macroexpanding and JAR'ing works fine. Created: 24/Feb/12  Updated: 18/May/13

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

Type: Defect Priority: Major
Reporter: Kevin Lynagh Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Code here:

https://gist.github.com/35fa11df7d7516abff50

Running lein uberjar on source containing the offending function, geo->svg, results in a non-working application.
However, if match is manually macroexpanded in the repl and the results pasted in, then the JAR works just fine.



 Comments   
Comment by Kevin Lynagh [ 24/Feb/12 2:27 PM ]

"non-working" meaning that the match always drops directly the :else clause.

Comment by Kevin Lynagh [ 24/Feb/12 6:09 PM ]

Updated code to minimal example. Problem persists with both Lein 1.7 and cake 0.6.3

Comment by David Nolen [ 25/Feb/12 7:35 PM ]

AOT bugs are a bit tricky to track down. Not sure how soon I'll be able to really dive into this one.





[MATCH-57] Non deterministic match behavior for seqs when AOT Created: 05/Apr/12  Updated: 18/May/13

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

Type: Defect Priority: Major
Reporter: Ronen Narkis Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Clojure 1.3

Leiningen 1.7.1 on Java 1.6.0_26

core.match "0.2.0-alpha9"



 Description   

The following source example:

https://github.com/narkisr/match-issue/blob/master/src/match_issue/core.clj

The defrule macro calls a function called lhs that use the match library,

this function calls it self recursively and print out the rest of body left to be matched,

When running lein compile two different results appear (in non deterministic fashion):

(when $message :> Message (== level 6) :from (entry-point event-stream))
($message :> Message (== level 6) :from (entry-point event-stream))
(Message (== level 6) :from (entry-point event-stream))
((== level 6) :from (entry-point event-stream))

This is the bug, as (== level 6) should be matched by:

[([([(o :when operator?) f s] :seq) :as c & r] :seq)]

In other cases the output is (the correct one):

(when $message :> Message (== level 6) :from (entry-point event-stream))
($message :> Message (== level 6) :from (entry-point event-stream))
(Message (== level 6) :from (entry-point event-stream))
((== level 6) :from (entry-point event-stream))
(:from (entry-point event-stream))
(entry-point event-stream)
()
()



 Comments   
Comment by David Nolen [ 06/Apr/12 11:03 AM ]

All AOT related issues w/o patches are low priority for the foreseeable future. They are simply too time consuming to track down and I don't have the bandwidth at the moment. I will get to them eventually, but if you want movement on this please submit a patch. I will happily apply it!

Comment by Ronen Narkis [ 07/Apr/12 7:53 PM ]

Hey David,

After going through the source code and some more in depth look I managed to understand what was going on, first iv stepped through the different stages

(def m (emit-matrix ['body]
'( [(['when & r] :seq)] (lhs r)
[(['accumulate & r] :seq)] (<< "accumulate(~(lhs r))")
[([bind ':> & r] :seq)] (<< "~{bind}:~(lhs r)"); pattern with bind
[([(t :when is-type?) & r] :seq)] (<< "{t}(lhs r)"); pattern
[([([(f :when acc-fn?) & args] :seq) & r] :seq)] (<< ",{f}{args}~(lhs r)" ); accumulate function
[([':from dest & r] :seq)] (<< "from ~(lhs dest) ~(lhs r)")
[([':over win & r] :seq)] (<< "over ~(window win) ~(lhs r)")
[([([(o :when operator?) f s] :seq) :as c & r] :seq)] (<< "(~(reduce str (map pr-str (to-infix c)))) ~(lhs r)")
[(['entry-point point & r] :seq)] (<< "entry-point \"~{point}\"~(lhs r)")
:else ""
)))

(def c (cm/compile m))

(pprint c)

(pprint (executable-form c))

The last pprint failed aot compilation:

$ lein compile

...
Caused by: java.lang.ClassCastException: clojure.core.match.WildcardPattern cannot be cast to java.lang.String

Which was very weird as I could clearly see that:

(deftype WildcardPattern [sym _meta]
IWildcardPattern
(sym [_] sym)
clojure.lang.IObj
(meta [_] _meta)
(withMeta [_ new-meta]
(WildcardPattern. sym new-meta))
Object
(toString [_]
(str sym)))

Then iv also tried to enabled trace:

(set-trace! true)

Which resulted with:

$ lein compile

...

TRACE: DAG: Column 0 : [#<SeqPattern #<LiteralPattern window> #<LiteralPattern :time> #<WildcardPattern t> #<WildcardPattern unit>>]
TRA at clojure.lang.Compiler.analyzeSeq(Compiler.java:6416)
at clojure.lang.Compiler.analyze(Compiler.java:6216)
at clojure.lang.Compiler.analyze(Compiler.java:6177)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5572)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5008)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3629)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6407)
at clojure.lang.Compiler.analyze(Compiler.java:6216)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6397)
at clojure.lang.Compiler.analyze(Compiler.java:6216)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:492)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6409)
at clojure.lang.Compiler.analyze(Compiler.java:6216)
at clojure.lang.Compiler.analyze(Compiler.java:6177)
at clojure.lang.Compiler.compile1(Compiler.java:6980)
at clojure.lang.Compiler.compile(Compiler.java:7046)
at clojure.lang.RT.compile(RTCE: DAG: Add switch-node on occurrence exp

The most weird thing was that on second compile it all went well, this raised a flag and my suspicion was that the core.match classes got compiled on the first run:

$ ls classes/

match$analyze_actions$analyze_action__1166.class
match$analyze_actions.class
match$backtrack_expr.class
match$bind_node.class
match$catch_error.class
match$check_matrix_args$check_pattern__1150.class
...

Then iv decided to AOT compile clojure.core match:

$ git checkout core.match-0.2.0-alpha9
$ git diff project.clj
-(defproject match "0.2.0-alpha10-SNAPSHOT"
+(defproject match "0.2.0-alpha10-aot"
:description "Optimized pattern matching and predicate dispatch for Clojure"
:source-path "src/main/clojure"

  • :test-path "src/test/clojure")
    + :test-path "src/test/clojure"
    + :aot [clojure.core.match]
    + )

After using the aot jar it all went smooth including passing my non deterministic case (which is deterministic but very confusing to track down),

In order to reproduce it its important to run:

$ lein clean
$ rm -rf lib

And only then run

$ lein compile

Otherwise the classes dir might contain AOT'ed classes and make it seem that even non-aot jar works fine (its enough to run lein compile once to cause the classes to get compiled),

The fix in my case is simple, just AOT ns.

Im not sure if this Is a bug in the way Clojure AOT its classes but I think that adding the AOT'ed classes to the default core match distro is a reasonable workaround

BTW when using master (and not the tag) iv stumbled upon:

Exception in thread "main" java.lang.AssertionError: Assert failed: Unknown predicate in [is-type?]

Which is a pred defined in my ns.





[MATCH-68] Vector match "underflow" => IndexOutOfBoundsException Created: 22/Apr/13  Updated: 18/May/13

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

Type: Defect Priority: Major
Reporter: Chas Emerick Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: File vector-rest-WIP.diff    
Patch: Code and Test

 Description   

This fails with 0.2.0-alpha12:

(match [[:x]]
  [[m n & _]] 1)

I expect nil, but an unguarded subvec call throws an IndexOutOfBoundsException.

A WIP patch is attached that fixes this (perhaps incorrectly) but which produced regressions (outside of core.match), e.g.

(match [[[:x "t"]]]
 [[[:x & a] & tail]] :a
 [[[:y & p] [:x & a] & tail]] :b)
=> nil

The patch also "fixes" this (by changing pattern-compare behaviour for rest VectorPattern s, but that leads to a regression in the vector-pattern-rest-2 testcase in core.match.

(Original discussion with further background here.)



 Comments   
Comment by Greg Chapman [ 24/Apr/13 5:26 PM ]

FWIW, I've been using the patch described here, and haven't yet run into any problems, though I also haven't used core.match that much. Anyway, with the change to subvec-inline, both of the cases here act as expected (producing nil and :a, respectively).

(I note looking at my patch that I'm doubly-evaluating ocr in the second overload; obviously that should be fixed with a let binding).

Comment by David Nolen [ 18/May/13 3:11 PM ]

The patch looks like it's going in the right direction. Can you explain why your patch without the pattern-compares case causes the second example to fail?





[MATCH-8] Implement (p|q)ba heuristics Created: 04/Sep/11  Updated: 04/Sep/11

Status: Open
Project: core.match
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   

We should implement the rest of Maranget's suggested heuristics.

p - needed prefix
q - constructor prefix
b - branching factor
a - constructor arity






[MATCH-9] use case for dispatching on literals Created: 04/Sep/11  Updated: 10/Oct/11

Status: Open
Project: core.match
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   

Would speed up literal matching considerably.






[MATCH-7] Eliminate distinction between leaf-bind-expr and bind-expr Created: 04/Sep/11  Updated: 21/Oct/11

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

Type: Task Priority: Trivial
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

We should have a better considered binding model that works for all cases instead of treating leaf nodes and regular binding as different cases.






Generated at Sun May 19 13:03:19 CDT 2013 using JIRA 4.4#649-r158309.