<< Back to previous view

[MATCH-82] Locals don't work in clojurescript Created: 18/Jul/13  Updated: 28/Jul/13  Resolved: 24/Jul/13

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

Type: Defect Priority: Critical
Reporter: George Fraser Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None
Environment:

clojure 1.5.1, lein-cljsbuild 0.3.2, core.match 0.2.0-rc4



 Description   
(let [x 1]
  (match 2
    x 1
    _ 2))

in Clojure => 2
in ClojureScript => 1



 Comments   
Comment by David Nolen [ 24/Jul/13 8:49 PM ]

fixed, http://github.com/clojure/core.match/commit/e270f057b0d9c0d0ce5c7aa4603b8b03e7c68093





[MATCH-83] Inconsistent [_ & _] behavior Created: 18/Jul/13  Updated: 28/Jul/13  Resolved: 24/Jul/13

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

Type: Defect Priority: Critical
Reporter: George Fraser Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None
Environment:

clojure 1.5.1
core.match 0.2.0-rc4



 Description   
(let [x [1 2]]
  (match x 
    [0 _ _ _] :a 
    [1 & _] :b 
    _ :c)) ; :c

(let [x [1 2]]
  (match x
    [1 & _] :b 
    [0 _ _ _] :a 
    _ :c)) ; :b

Both clojure and clojurescript



 Comments   
Comment by David Nolen [ 24/Jul/13 8:48 PM ]

fixed, http://github.com/clojure/core.match/commit/ae2bc9c581c2e95b24270498549e97d59f379b1f





[MATCH-35] Bug in seq pattern matching Created: 27/Oct/11  Updated: 28/Jul/13  Resolved: 16/Jun/13

Status: Closed
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: Completed 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)))

Comment by David Nolen [ 16/Jun/13 10:38 PM ]

fixed, http://github.com/clojure/core.match/commit/37564e32d34547e7d8a71f7abc631cce9585dd4e





[MATCH-52] Pattern Map's aren't working Created: 12/Feb/12  Updated: 28/Jul/13  Resolved: 14/Aug/12

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

Type: Defect Priority: Critical
Reporter: Jason Jackson Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File 0001-map-matching-always-checks-for-presence-of-key-even-.patch     Text File 0001-Map-matching-should-always-check-for-presence-of-key.patch     File patch    

 Description   

Neither of these work as expected:

(match [ {:type :consumed :value 4}]
[({:uid uid :modifiers ms} :only [:uid :modifiers])] :a0)

(match [ {:type :consumed :value 4}]
[{:uid uid :modifiers ms} ] :a0)

Tried these versions:
"0.2.0-alpha10-SNAPSHOT"
"0.2.0-alpha9"



 Comments   
Comment by Jason Jackson [ 12/Feb/12 11:33 PM ]

I tried to use :when to detect when key is not found. But this doesn't work either.
(match {:foo 3}
{:uid (uid :when #(not (nil? %)))} :a0)

Comment by David Nolen [ 14/Feb/12 4:31 PM ]

Looks good, but can you create the patch so that it contains your credentials as well as test cases? Thanks!

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

added unit tests and attribution info.

Comment by Kevin Lynagh [ 13/Aug/12 11:18 PM ]

I've manually applied this patch to the latest master and verified that it fixes the issue.
Patch attached and also available on the Github:

https://github.com/lynaghk/core.match/tree/issue-52

EDIT: spoke too soon; I can't seem to upload the patch to JIRA as a commenter. Available here: https://github.com/lynaghk/core.match/compare/issue-52.patch

I've also added a commit on top to get ClojureScript support.
The implementation feels a bit gross to me (it inlines the clojure core.match val-at* function, basically) but a nicer solution isn't obvious to me given ClojureScript's macro/runtime divide.

Comment by Kevin Lynagh [ 14/Aug/12 9:05 PM ]

Updated Jason Jackson's patch with CLJS support.

Comment by David Nolen [ 14/Aug/12 9:11 PM ]

Fixed, http://github.com/clojure/core.match/commit/7f73cee3f78417f1fb59bcbb4a8cda52de22efbd





[MATCH-47] vector patterns dispatch on count after dispatching on type Created: 23/Dec/11  Updated: 28/Jul/13  Resolved: 16/Jun/13

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

The current behavior just creates complications.



 Comments   
Comment by David Nolen [ 16/Jun/13 10:22 PM ]

as of http://github.com/clojure/core.match/commit/59df5b32b3c06b0038f76ccb88670fa9f42e5547 we always check size when applicable





[MATCH-36] throw on unsuccessful match Created: 27/Oct/11  Updated: 28/Jul/13  Resolved: 15/Jun/13

Status: Closed
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: Completed Votes: 1
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.



 Comments   
Comment by David Pollak [ 28/May/13 10:20 AM ]

FWIW, I think the existing behavior (returning a nil) is the correct behavior. If a user wants to throw an exception, they can add an :else clause.

Why is the existing behavior correct?

Think of a Map as a match. When you look up a key that is not in the Map, you get a nil. There are simple ways to add additional behavior to maps to return something other than a nil, but the default is nil.

A Map, like a pattern match, is defined at some values of the input and not other values of the input.

Comment by David Nolen [ 28/May/13 10:26 AM ]

The behavior aligns with Clojure's case. The issue is that Clojure being dynamically typed (and match actively taking advantage of this) can't really do exhaustiveness checking in all cases - I think throwing is desirable, and experience seems to suggest this as well - otherwise nils will flow in likely unintentional ways. Users can always add the explicit nil return if they like. I suspect users will not do this.

Comment by David Nolen [ 15/Jun/13 10:27 PM ]

fixed, http://github.com/clojure/core.match/commit/63e56f524e60644460a9e43e1312966c42c3a5d5





[MATCH-84] Rest does not work on vectors? Created: 21/Jul/13  Updated: 28/Jul/13  Resolved: 24/Jul/13

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

Type: Defect Priority: Critical
Reporter: Yongqian Li Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None


 Description   
(let [v [3 2 3 4]]
  (match [v]
    [[1 1 3]] :a0
    [[3 & r]] :a2))

Gives "java.lang.IllegalArgumentException: No matching clause: [3 2 3 4]"

(let [v [3 2 3 4]]
  (match [v]
    [[3 & r]] :a2))
=> :a2, as expected

(let [v [3 2 3 4]]
  (match [v]
    [[1 1 3]] :a0
    [[3 2 3 4]] :a2))
=> :a2, as expected


 Comments   
Comment by David Nolen [ 24/Jul/13 8:48 PM ]

fixed, http://github.com/clojure/core.match/commit/ae2bc9c581c2e95b24270498549e97d59f379b1f





[MATCH-92] Map matching is broken for keywords with periods Created: 13/Jan/14  Updated: 14/Jan/14  Resolved: 14/Jan/14

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

Type: Defect Priority: Critical
Reporter: Luke VanderHart Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None
Environment:

Clojure 1.6 alpha


Attachments: Text File 0001-test-and-fix-for-MATCH-92.patch    
Patch: Code and Test

 Description   

The compilation generates invalid code in the case where a map keyword contains a period (which is a legal character for a keyword).

 
(match {:a.b 1}
   {:a.b _} :foo)
;; CompilerException java.lang.ClassFormatError: Illegal field name "ocr_5762_0__5765_a.b__5768"

Among other things, this precludes the use of core.match on Datomic data.



 Comments   
Comment by David Nolen [ 13/Jan/14 1:54 PM ]

Thanks for the report seems simple to fix.

Comment by Luke VanderHart [ 13/Jan/14 1:57 PM ]

Awesome. Are you looking at it right now? Otherwise I might dig into the code myself since this is blocking me at the moment.

Comment by Luke VanderHart [ 13/Jan/14 2:14 PM ]

Uploaded patch

Comment by David Nolen [ 13/Jan/14 2:34 PM ]

Patch looks good to me. Thanks! I will apply later today and cut another release.

Comment by David Nolen [ 14/Jan/14 8:29 AM ]

fixed, https://github.com/clojure/core.match/commit/eee5c814ce3e8256b0450cbeafb7f917418ebeaf





[MATCH-12] Migrate to Maven Created: 04/Sep/11  Updated: 28/Jul/13  Resolved: 23/Sep/11

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

Type: Task Priority: Major
Reporter: Ambrose Bonnaire-Sergeant Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Waiting On: David Nolen

 Description   

AFAIK we need to migrate to Maven for Contrib projects.

I used core.logic as a template and it seems to have been successful. Anything missing?

https://github.com/clojure/core.match/commit/5146212edecbd8d765028e165352d20005b44cc3



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

This looks OK to me, do all tests pass?

Comment by Ambrose Bonnaire-Sergeant [ 05/Sep/11 10:56 AM ]

Yep, all tests pass.





[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: 28/Jul/13  Resolved: 15/Jun/13

Status: Closed
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: Completed 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.

Comment by David Nolen [ 15/Jun/13 10:00 PM ]

this AOT case at least is resolved on master.





[MATCH-26] Bug in the way that constructor set for a column is computed Created: 05/Oct/11  Updated: 28/Jul/13  Resolved: 09/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   
(let [x '(1 2) y 1]
  (match [x y]
    [([1] :seq) _] :a0
    [_ 1] :a1
    [([1 2] :seq) _] :a2
    [_ 2] :a3
    :else :a4))

This returns :a2 when it should return :a1



 Comments   
Comment by David Nolen [ 09/Oct/11 2:22 PM ]

Fixed, https://github.com/clojure/core.match/commit/efa880320fc235536690ba8af078a59c17f3321d





[MATCH-14] Vector Pattern bug when patterns not all of the same length Created: 13/Sep/11  Updated: 28/Jul/13  Resolved: 26/Sep/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

(let [v [[1 2]]]
(match [v]
[[3 1]] :a0
[[([1 a] :as b)]] [:a1 a b]))

Throws out of bounds exception error



 Comments   
Comment by David Nolen [ 26/Sep/11 5:57 AM ]

Fixed, https://github.com/clojure/core.match/commit/2f5d82bfb6031325114b9a5aaad975fb60dd7bd3





[MATCH-24] Setting *warn-on-reflection* affects all code using core.match Created: 03/Oct/11  Updated: 28/Jul/13  Resolved: 03/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

Setting warn-on-reflection affects all use of core.match.

Please remove all cases where warn-on-reflection is set.

This can be set by the pom for the project, rather than in source, so it doesn't affect code using core.match.



 Comments   
Comment by David Nolen [ 03/Oct/11 7:38 AM ]

Fixed, https://github.com/clojure/core.match/commit/f75152edb697cff9bbe9070478b5bc0105f140ca

Do you have an example of setting it in the POM?

Comment by Hugo Duncan [ 03/Oct/11 11:32 AM ]

Thanks!

I assume the clojure build is using clojure-maven-plugin, in which case it is just a matter of setting warnOnReflection. Something like this (untested):

<build>
 <plugins>
  <plugin>
    <groupId>com.theoryinpractise</groupId>
    <artifactId>clojure-maven-plugin</artifactId>
    <configuration>
      <warnOnReflection>true</warnOnReflection>
    </configuration>
  </plugin>
 </plugins>
</build>




[MATCH-6] Nested rest pattern in vector patterns cause infinite loop Created: 04/Sep/11  Updated: 28/Jul/13  Resolved: 26/Sep/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

Nested rest patterns combined w/ vector patterns cause an infinite loop.



 Comments   
Comment by David Nolen [ 26/Sep/11 5:59 AM ]

See MATCH-17 and MATCH-14





[MATCH-50] locals pattern matching issue Created: 12/Jan/12  Updated: 28/Jul/13  Resolved: 25/Feb/12

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   
(let [a 1]
    (match [1 2]
      [1 3] :a0
      [a 2] :a1
      :else :a2)) ;; :a2


 Comments   
Comment by David Nolen [ 25/Feb/12 6:49 PM ]

Fixed, https://github.com/clojure/core.match/commit/ac92c6df3f70f56fbe12f9d3f46585e66102c50b





[MATCH-81] large pattern problematic for ClojureScript Created: 16/Jul/13  Updated: 28/Jul/13  Resolved: 16/Jul/13

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   
(ns test
  (:use-macros [clojure.core.match.js :only [match]])
  (:require [clojure.core.match]))

(defn get-meaning
        [paragraph line blank mode theme annotation]
                (match
                        [paragraph  line    (> blank 0) mode    theme   annotation  ]
                        [_          _       true        _       _       _           ] "monaco-enter"
                        [_          _       _           _       true    _           ] "monaco-theme"
                        [_          _       _           _       false   true        ] "monaco-annotation"
                        [_          _       false       :theme  _       false       ] "monaco-note"
                        [0          0       false       _       false   false       ] "monaco-outcome"
                        [0          _       false       _       false   false       ] "monaco-perex"
                        [1          _       false       _       false   false       ] "monaco-next-action"
                        [2          _       false       _       false   false       ] "monaco-following-action"
                        [_          _       false       nil     false   false       ] "monaco-supplemental"
                        :else "monaco-generic"
                        )
        )


 Comments   
Comment by David Nolen [ 16/Jul/13 6:26 PM ]

When addressing this patch we should do several things - reorg the namespaces, allow CLJS user to pick their compilation strategy explicitly - if the backtrack solution is chosen we should throw if recur is present.

Comment by David Nolen [ 16/Jul/13 8:57 PM ]

fixed http://github.com/clojure/core.match/commit/f19bfef48ed13f396fd0140cc1a90b2218f26579





[MATCH-71] map patterns don't exhibit as much test sharing as expected Created: 18/Jun/13  Updated: 28/Jul/13  Resolved: 18/Jun/13

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

`map-pattern-match-1` in the test cases tests the value for :b only in the first line, it backtracks and considers :a instead of looking the second value for :b first.

for example for:

(match [x]
  [{:a _ :b 2}] :a0
  [{:a 1 :b 1}] :a1)

The decision tree looks far too complicated.



 Comments   
Comment by David Nolen [ 18/Jun/13 11:42 PM ]

fixed, http://github.com/clojure/core.match/commit/babb964413c2dc0058b4bb36f9a903a9de74f755





[MATCH-51] Fail to match empty vector Created: 21/Jan/12  Updated: 28/Jul/13  Resolved: 15/Jun/13

Status: Closed
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: Completed 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

Comment by David Nolen [ 15/Jun/13 10:03 PM ]

resolved in master, added test case http://github.com/clojure/core.match/commit/b21d1a09e0d495003fc45ca48568355609ed69bd





[MATCH-46] :or leaks into the matches Created: 22/Dec/11  Updated: 28/Jul/13  Resolved: 22/Dec/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

Macroexpanding an match expression with an :or pattern will show this.



 Comments   
Comment by David Nolen [ 22/Dec/11 12:52 AM ]

Fixed, https://github.com/clojure/core.match/commit/c1430c98937f31a0c8d2a92d793b0795b2c9a1d6





[MATCH-42] quoted symbols should be treated as literals Created: 30/Nov/11  Updated: 28/Jul/13  Resolved: 30/Nov/11

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

Type: Defect Priority: Major
Reporter: Steve Miner Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File match-42-quoted-symbol.patch    

 Description   

Reported on the Clojure mailing list:

From: Alex Miller <alex@puredanger.com>
Subject: Symbol matching in core.match
Date: November 30, 2011 2:49:43 PM EST
To: Clojure <clojure@googlegroups.com>
Reply-To: clojure@googlegroups.com

I've been working with core.match some this week and finding it pretty
nice. However, I have a common case (for me) that is not well handled
right now via core.match: matching symbols. Say that I wrote a match
like this:

;; translate (+ x (+ y z)) to (+ x y z)
(let [e '(+ 1 (+ 2 3))]
(match [e]
[([+ x ([+ y z] :seq)] :seq)] (+ x y z)))

You will see this error:
Pattern row 1: Pattern row reuses wildcards in [([+ x ([+ y
z] :seq)] :seq)]. The following wildcards are ambiguous: +. There's
no guarantee that the matched values will be same. Rename the
occurrences uniquely.

Any symbol inside a pattern row is treated as a bind variable. + is a
symbol. You can achieve this with guards:

(defn +? [s] (= '+ s))

(let [e '(+ 1 (+ 2 3))]
(match ['(+ 1 (+ 2 3))]
[([(_o1 :when +?) x ([(_o2 :when +?) y z] :seq)] :seq)] (list
'+ x y z)))

but, yuck. I can imagine using the reserved ()'s with additional keys
(:symbol or :sym) to do symbol matching like (:symbol +) but also,
yuck. The simplest idea I came up with was:

(let [e '(+ 1 (+ 2 3))]
(match [e]
[(['+ x (['+ y z] :seq)] :seq)] ('+ x y z)))

These come through as (quote x) although the error reporting goes a
little off the rails:
Pattern row 1: Pattern row reuses wildcards in [([(quote +) x ([(quote
+) y z] :seq)] :seq)]. The following wildcards are ambiguous: quote.
There's no guarantee that the matched values will be same. Rename the
occurrences uniquely.

However, that seems fixable and you could then use (quote x) as a
signal to do symbol matching. If I can figure out what the hell I'm
doing in core.match then I'd be happy to work on a patch.



 Comments   
Comment by Steve Miner [ 30/Nov/11 4:56 PM ]

Skip anything that's quoted when looking for duplicate symbol names. Added a test for the reported case.

Comment by Steve Miner [ 30/Nov/11 4:57 PM ]

patch attached

Comment by David Nolen [ 30/Nov/11 6:52 PM ]

Fixed, https://github.com/clojure/core.match/commit/6721be4fba74561038539e12667bc04cc5fc94cc





[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: 28/Jul/13  Resolved: 02/Jun/13

Status: Closed
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: Duplicate 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.

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

This is a variant of MATCH-70. You can not specify that some keys must be present by specifying the key and the specifying that the value of the key is a wildcard.





[MATCH-77] *recur-present* compilation process is not consistent with default compilation process Created: 22/Jun/13  Updated: 28/Jul/13  Resolved: 23/Jun/13

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

We get three failing tests if we compile all the tests with recur-present set to true. We also get a code size error but there's nothing to be done about that on the JVM.



 Comments   
Comment by David Nolen [ 23/Jun/13 8:37 PM ]

fixed, http://github.com/clojure/core.match/commit/d93679d488ba4076243009ff629b21ea3083007c





[MATCH-13] Invalid method Code length when generating red black tree matcher Created: 05/Sep/11  Updated: 28/Jul/13  Resolved: 28/Sep/11

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

Type: Defect Priority: Major
Reporter: Thomas Greve Kristensen Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None
Environment:

lein --version
Leiningen 1.4.2 on Java 1.6.0_26 Java HotSpot(TM) 64-Bit Server VM
The project.clj file is as follows:
(defproject redblack "1.0.0-SNAPSHOT"
:description "FIXME: write"
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
[org.clojure/core.match "0.2.0-SNAPSHOT"]]
:dev-dependencies [[swank-clojure "1.3.0-SNAPSHOT"]])
core.match is compiled and installed using the above environment by issuing mvn install



 Description   

The issue is the same as stated on
https://github.com/swannodette/match/issues/54
but moved here as a part of moving match to Clojure contrib.

Here is a copy of the text from the issue above:

After having forked the latest version on branch and compiling I attempted to execute the infamous red-black tree rebalancing code.

(let [node nil]
(match/match
[node]
[([:black [:red [:red a x b] y c] z d] |
[:black [:red a x [:red b y c]] z d] |
[:black a x [:red [:red b y c] z d]] |
[:black a x [:red b y [:red c z d]]])]
[:red [:black a x b] y [:black c z d]]))
The good news is that issue issue 47 is indeed resolved. The bad news is that a new issue has cropped up, namely that the ClassFormatError with the message

error: java.lang.ClassFormatError: Invalid method Code length 78596 in class file redblack/core$eval3306 (core.clj:10)
is raised.



 Comments   
Comment by David Nolen [ 05/Sep/11 3:43 PM ]

Do you encounter this error at the REPL?

Comment by Thomas Greve Kristensen [ 05/Sep/11 11:26 PM ]

Sort of - it is encountered when connecting to the REPL using swank form emacs.

Comment by David Nolen [ 05/Sep/11 11:43 PM ]

Can you elaborate the exact steps? What OS?

I'm interested in knowing the details since I haven't run into it myself - solving http://dev.clojure.org/jira/browse/MATCH-1 should address this problem.

Comment by Thomas Greve Kristensen [ 06/Sep/11 2:21 AM ]

I have executed all my tests on a mac os x lion 10.7.1. I've just added my (failing) code to github, it can be found here:
https://github.com/tgk/RedBlackTreesUsingMatch

The steps are as follows:
lein deps
lein swank
From aquaemacs, connect to swank using slime-connect
Open the file src/redblack/core.clj
Execute the entire file (C-c C-k if memory serves)

Sorry for the very brief description, but I'm at work...

Comment by Thomas Greve Kristensen [ 06/Sep/11 12:33 PM ]

Here's a bit longer description:

First, I cloned clojure.core.match.core and installed it using
mvn install

I have added a :main description to the project above. To make it fail I can simply use
lein run

Comment by Thomas Greve Kristensen [ 07/Sep/11 1:23 PM ]

I have also tried using 1.3.0-master-SNAPSHOT of clojure but with no luck. Which version of java are you using?

Comment by Thomas Greve Kristensen [ 07/Sep/11 1:23 PM ]

I have also tried using 1.3.0-master-SNAPSHOT of clojure but with no luck. Which version of java are you using?

Comment by David Nolen [ 07/Sep/11 1:52 PM ]

Sorry been a bit swamped so I haven't had a chance to go through your exact steps (I'm sure I'll get the same error). Again I'm pretty confident I know why the red black tree pattern generates so much code. Adding backtracking will be a significant code size optimization.

Comment by David Nolen [ 26/Sep/11 6:59 AM ]

See MATCH-1

Comment by David Nolen [ 28/Sep/11 10:47 PM ]

Fixed now in master.





[MATCH-55] Matching a sequence with just a rest pattern fails to compile Created: 21/Mar/12  Updated: 28/Jul/13  Resolved: 16/Jun/13

Status: Closed
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: Completed 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



 Comments   
Comment by David Nolen [ 16/Jun/13 4:13 PM ]

fixed, http://github.com/clojure/core.match/commit/d09ef3bf3d4264aee0c6da5436b760a996811e17





[MATCH-16] Empty Vector Patterns Fail to Match Created: 25/Sep/11  Updated: 28/Jul/13  Resolved: 25/Sep/11

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

Type: Defect Priority: Major
Reporter: Ambrose Bonnaire-Sergeant Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None


 Description   

(match [[]]
[[]] "asdf")
#<RuntimeException java.lang.RuntimeException: java.lang.Exception: No match found. Followed 0 branches. Breadcrumbs: []>

Macro-expand'd:

(let*
[ocr-4856 []]
(clojure.core/cond
(clojure.core/and
(clojure.core/instance? clojure.lang.IPersistentVector ocr-4856)
(clojure.core/= (clojure.core/count ocr-4856) 1)) (clojure.core/let
[ocr-4856_0__4857
(clojure.core/nth
ocr-4856
0)]
(clojure.core/cond
(clojure.core/=
ocr-4856_0__4857
nil)
"asdf"
:else
(throw
(java.lang.Exception.
(clojure.core/str
"No match found. "
"Followed "
1
" branches."
" Breadcrumbs: "
'[(clojure.core/and
(clojure.core/instance?
clojure.lang.IPersistentVector
ocr-4856)
(clojure.core/=
(clojure.core/count
ocr-4856)
1))])))))
:else (throw
(java.lang.Exception.
(clojure.core/str
"No match found. "
"Followed "
0
" branches."
" Breadcrumbs: "
'[])))))

Clearly this test is the issue: (clojure.core/= (clojure.core/count ocr-4856) 1))



 Comments   
Comment by Ambrose Bonnaire-Sergeant [ 25/Sep/11 5:15 AM ]

Bah, I'll try again:

(match [[]] 
         [[]] "asdf")
#<RuntimeException java.lang.RuntimeException: java.lang.Exception: No match found. Followed 0 branches. Breadcrumbs: []>
(let*
  [ocr-4856 []]
  (clojure.core/cond
    (clojure.core/and
      (clojure.core/instance? clojure.lang.IPersistentVector ocr-4856)
      (clojure.core/= (clojure.core/count ocr-4856) 1)) (clojure.core/let 
                                                          [ocr-4856_0__4857
                                                           (clojure.core/nth
                                                             ocr-4856
                                                             0)]
                                                          (clojure.core/cond
                                                            (clojure.core/=
                                                              ocr-4856_0__4857
                                                              nil)
                                                            "asdf"
                                                            :else
                                                            (throw
                                                              (java.lang.Exception.
                                                                (clojure.core/str
                                                                  "No match found. "
                                                                  "Followed "
                                                                  1
                                                                  " branches."
                                                                  " Breadcrumbs: "
                                                                  '[(clojure.core/and
                                                                      (clojure.core/instance?
                                                                        clojure.lang.IPersistentVector
                                                                        ocr-4856)
                                                                      (clojure.core/=
                                                                        (clojure.core/count
                                                                          ocr-4856)
                                                                        1))])))))
    :else (throw
            (java.lang.Exception.
              (clojure.core/str
                "No match found. "
                "Followed "
                0
                " branches."
                " Breadcrumbs: "
                '[])))))
Comment by David Nolen [ 25/Sep/11 5:53 PM ]

Fixed, https://github.com/clojure/core.match/commit/9ba924ddd4e8cf9f08d44f2362bf04add1b69ae1





[MATCH-80] matching literals is too optimistic Created: 03/Jul/13  Updated: 28/Jul/13  Resolved: 16/Jul/13

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   
(m/match [:r :d]
  [:s :d] nil
  [:r :t] nil
  [:r :d] :x
  [:s :t] nil)

If the order of the first two clauses is flipped we will run into trouble. The constant literal match optimization is too optimistic. We should put the literals into a set to know how many we can test together.



 Comments   
Comment by David Nolen [ 16/Jul/13 6:25 PM ]

fixed in master for rc3





[MATCH-66] Cannot match entire/single value Created: 06/Jan/13  Updated: 28/Jul/13  Resolved: 18/May/13

Status: Closed
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: Completed Votes: 1
Labels: None


 Description   
=> (match 3 x x)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: ocr-34984 in this context, compiling:(NO_SOURCE_PATH:1:1) 
=> (macroexpand '(match 3 x x))
(let* [x ocr-35001] x)

(Discussed briefly here.)



 Comments   
Comment by David Nolen [ 18/May/13 2:18 PM ]

fixed, http://github.com/clojure/core.match/commit/02a833efb959e0518f264ded3b98ce4215b5622c





[MATCH-21] Head-Tail Pattern Matching Fails for Lists Created: 30/Sep/11  Updated: 28/Jul/13  Resolved: 02/Oct/11

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

Type: Defect Priority: Major
Reporter: Ambrose Bonnaire-Sergeant Assignee: David Nolen
Resolution: Declined Votes: 0
Labels: None


 Description   

Head-tail pattern matching only seems to work with vectors.

Commit: https://github.com/clojure/core.match/commit/9f4919d855be09a1b32f9e5563ac1c3f5bace642

The following code falls through. (macroexpand appended)

(let [x '(1 2 3)]
  (match [x]
         [[a & as]] :a))
(try
  (clojure.core/cond
    (clojure.core/instance? clojure.lang.IPersistentVector x) (try
                                                                (clojure.core/let 
                                                                  [x_left__3201
                                                                   (clojure.core/subvec
                                                                     x
                                                                     0
                                                                     1)]
                                                                  (clojure.core/cond
                                                                    (clojure.core/and
                                                                      (clojure.core/instance?
                                                                        clojure.lang.IPersistentVector
                                                                        x_left__3201)
                                                                      (clojure.core/=
                                                                        (clojure.core/count
                                                                          x_left__3201)
                                                                        1))
                                                                    (clojure.core/let 
                                                                      [a
                                                                       (clojure.core/nth
                                                                         x_left__3201
                                                                         0)
                                                                       as
                                                                       (clojure.core/subvec
                                                                         x
                                                                         1)]
                                                                      :a)
                                                                    :else
                                                                    (throw
                                                                      clojure.core.match.core/backtrack)))
                                                                (catch
                                                                  java.lang.Exception
                                                                  e__2436__auto__
                                                                  (throw
                                                                    clojure.core.match.core/backtrack)))
    :else (throw clojure.core.match.core/backtrack))
  (catch
    java.lang.Exception
    e__2437__auto__
    (throw clojure.core.match.core/backtrack)))


 Comments   
Comment by David Nolen [ 02/Oct/11 11:35 AM ]

This is the expected behavior. If you want to match seqs you have to use the seq pattern syntax.





[MATCH-10] map pattern keys should be allowed to be heterogenous types Created: 04/Sep/11  Updated: 28/Jul/13  Resolved: 27/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

Right now they fail since heterogenous keys can't be sorted.



 Comments   
Comment by David Nolen [ 27/Oct/11 11:39 PM ]

Fixed, https://github.com/clojure/core.match/commit/3a2e5598b6fc7ad52caa0869802d0ed80ba54124





[MATCH-34] remove infix or pattern syntax, use (:or x y z) instead Created: 21/Oct/11  Updated: 28/Jul/13  Resolved: 27/Oct/11

Status: Closed
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: Completed Votes: 1
Labels: None


 Comments   
Comment by David Nolen [ 27/Oct/11 11:17 PM ]

Fixed, https://github.com/clojure/core.match/commit/0195f7211d44e15d40a35445b4882fcaf5bc9fb6





[MATCH-25] Map pattern :only case still not right Created: 05/Oct/11  Updated: 28/Jul/13  Resolved: 06/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   
(let [m {:a 1 :b 2}]
  (match [m]
    [({:a 1} :only [:a])] :a0
    :else :a1))

We get :a0 instead of :a1



 Comments   
Comment by David Nolen [ 06/Oct/11 8:28 PM ]

Fixed, https://github.com/clojure/core.match/commit/3407090009b447b594a7c361c8891f9b6e8f72bb





[MATCH-1] Investigate non-overlapping pattern optimization via pre-allocated exception for backtracking Created: 04/Sep/11  Updated: 28/Jul/13  Resolved: 28/Sep/11

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

Type: Task Priority: Major
Reporter: David Nolen Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None


 Description   

The red black tree balance pattern mentioned by tgk generates enough code that the JVM will not inline it. Maranget's algorithm basically implements backtracking by passing along wildcard matches with actual matches. For non-overlapping patterns like the red black tree balance pattern this means exponential code size.

For such patterns where none of the actions involve recur we could implement backtracking with a pre-allocated exception.

http://blogs.oracle.com/jrose/entry/longjumps_considered_inexpensive



 Comments   
Comment by David Nolen [ 28/Sep/11 10:46 PM ]

Fixed now in master.





[MATCH-19] Analyze action bodies for the presence of recur, if recur is present do not use backtracking Created: 29/Sep/11  Updated: 28/Jul/13  Resolved: 02/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

A post about matchure on the ML reminded about my original line of thinking. We should not use the backtracking solution if we detect the presence of recur in any of the action bodies. If it is present we should use the old compilation mechanism.



 Comments   
Comment by David Nolen [ 02/Oct/11 12:56 PM ]

Fixed, https://github.com/clojure/core.match/commit/af4ca0425daee7dd7421716f6a151d2dda988a9a





[MATCH-20] Doesn't match 'head & tail' in vector matching. Created: 29/Sep/11  Updated: 28/Jul/13  Resolved: 02/Oct/11

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

Type: Defect Priority: Major
Reporter: Nikita Beloglazov Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None


 Description   

Following code:

(match [[:plus 1 2 3]]
[[:pow arg pow]] 0
[[:plus & args]] 1
:else 2)

Returns 2, but must return 1.

If we delete first clause it works:

(match [[:plus 1 2 3]]
[[:plus & args]] 1
:else 2)

Returns 1.



 Comments   
Comment by Nikita Beloglazov [ 01/Oct/11 1:11 PM ]

Also works with [:plus 1 2] - vector size is now 3, was 4:

(match [[:plus 1 2]]
  [[:pow arg pow]] 0
  [[:plus & args]] 1
  :else 2)
=> 1
Comment by David Nolen [ 01/Oct/11 1:13 PM ]

I have a pretty good idea what's wrong here as well as the fix. Hope to get this resolved in the next couple of days.

Comment by David Nolen [ 02/Oct/11 12:25 PM ]

Fixed, https://github.com/clojure/core.match/commit/02f2ab62cba3d1017c2590b04946cb2c92190635





[MATCH-59] Misleading comment in clojure.core.match.bits Created: 19/May/12  Updated: 28/Jul/13  Resolved: 18/May/13

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

Type: Enhancement Priority: Major
Reporter: Thomas Greve Kristensen Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None


 Description   

I was looking at the code for clojure.core.match.bits, and there seems to be a reference to an example of parsing a dgram. The code looks to be broken or incomplete, or is it my understanding of it that is lacking?

If it isn't done, are there any plans to finish it up?



 Comments   
Comment by David Nolen [ 18/May/13 2:21 PM ]

The bits and array namespaces are experimental I've left a comment in both namespaces that states that.

http://github.com/clojure/core.match/commit/511b786b9545f5c00a629fa27be0ee2a6b01e2ae





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

Status: Closed
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: Duplicate 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.



 Comments   
Comment by David Nolen [ 02/Jun/13 11:37 AM ]

also a variant of MATCH-70





[MATCH-62] ClojureScript map-matching should use cljs.core/ILookup, not cljs.core.ILookup Created: 30/Jun/12  Updated: 28/Jul/13  Resolved: 01/Jul/12

Status: Closed
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: Completed Votes: 0
Labels: None

Attachments: Text File cljs_lookup.patch    

 Description   

The latter form is an implementation detail and doesn't work in the latest cljs compiler release.



 Comments   
Comment by Kevin Lynagh [ 30/Jun/12 12:10 PM ]

Patch against master to use cljs.core/ILookup. Also available at https://github.com/lynaghk/core.match/tree/62-cljs-protocol

Comment by David Nolen [ 01/Jul/12 11:05 AM ]

fixed, http://github.com/clojure/core.match/commit/241a3a3ab5344cc7c97fb3ab0b3783ce97b09f6d





[MATCH-27] match eats exceptions Created: 06/Oct/11  Updated: 28/Jul/13  Resolved: 06/Oct/11

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

Type: Defect Priority: Major
Reporter: mindslight Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None
Environment:

match 0.2.0-alpha4, clojure 1.2.0



 Description   

user=> (match-1 :a :a (throw (Exception.)) :else :c)
:c

I would expect the exception to flow through the match. Instead, it gets eaten and one is left wondering why the proper clause "isn't matching".



 Comments   
Comment by David Nolen [ 06/Oct/11 10:51 PM ]

Fixed, https://github.com/clojure/core.match/commit/94f240dee09434ab87d2f901c647fdbd73792e89





[MATCH-18] IndexOutOfBound exception using '&' in vector matching. Created: 28/Sep/11  Updated: 28/Jul/13  Resolved: 28/Sep/11

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

Type: Defect Priority: Major
Reporter: Nikita Beloglazov Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None


 Description   

Following sample causes IndexOutOfBound exception.

(match [[:pow :x 2]]
[[:pow arg pow]] 0
[[:mult & args]] 1
:else 2)

Result: IndexOutOfBound

But if we delete '&' everything works fine:

(match [[:pow :x 2]]
[[:pow arg pow]] 0
[[:mult args]] 1
:else 2)

Result: 0



 Comments   
Comment by David Nolen [ 28/Sep/11 8:23 PM ]

Fixed, https://github.com/clojure/core.match/commit/e0677eec1dac387e369886a72c19f75262cecd68





[MATCH-67] match broken on ClojureScript >= 88b36c1 Created: 14/Feb/13  Updated: 28/Jul/13  Resolved: 15/Feb/13

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

The ClojureScript example in core.match's readme is failing at the moment, using core.match 0.2.0-alpha11:

(ns foo.bar
  (:use-macros [clojure.core.match.js :only [match]]))

(match [(mod 5 3) (mod 5 5)]
      [0 0] "FizzBuzz"
      [0 _] "Fizz"
      [_ 0] "Buzz"
      :else n)

ClojureScript:foo.bar> WARNING: Use of undeclared Var foo.bar/e__4345__auto__ at line 4 
clojure.lang.ExceptionInfo: Unsupported binding form: (if (clojure.core/identical? e__4345__auto__ 0) (do (clojure.core/let [ocr-5230 (mod 5 5) ocr-5229 (mod 5 3)] (try (clojure.core/cond (clojure.core/= ocr-5230 0) (clojure.core/let [G__5226 ocr-5229] "Buzz") :else (throw 0)) (catch e__4345__auto__ (if (clojure.core/identical? e__4345__auto__ 0) (do (clojure.core/let [G__5228 ocr-5230 G__5227 ocr-5229] n)) (throw e__4345__auto__)))))) (throw e__4345__auto__)) at line 4  {:tag :cljs/analysis-error, :file nil, :line 4}

The same error is produced with any usage of match in ClojureScript AFAICT, not just the README example. However, all is well with core.match AFAICT under Clojure, and if you use older revs of ClojureScript, e.g. r1552. I did a bisect, and found that this is the first ClojureScript commit with which the example does not work:

https://github.com/clojure/clojurescript/commit/88b36c1

Reverting it with master results in proper evaluation of the match, modulo the warning.

I don't see any obvious reason why the above would cause any problems, and some moderate digging based on what I know about ClojureScript didn't yield any ah-ha! moments.



 Comments   
Comment by David Nolen [ 15/Feb/13 5:21 PM ]

fixed http://github.com/clojure/core.match/commit/3bab92b6620dccdcb9e55941af4599e3adf78a6e

Comment by Chas Emerick [ 15/Feb/13 7:51 PM ]

Thanks for looking at this!





[MATCH-76] CLJS prim array matching Created: 20/Jun/13  Updated: 28/Jul/13  Resolved: 22/Jun/13

Status: Closed
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: Completed Votes: 0
Labels: None


 Comments   
Comment by David Nolen [ 22/Jun/13 10:53 AM ]

fixed, http://github.com/clojure/core.match/commit/a126d33ae6ad6a19ff58c3f20e0002182bf99635





[MATCH-11] The order of pattern rows should be preserved Created: 04/Sep/11  Updated: 28/Jul/13  Resolved: 25/Sep/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

Sometimes pattern rows are not preserved in the user defind order. Fix this and create the tests to show that this property is preserved.



 Comments   
Comment by David Nolen [ 25/Sep/11 8:50 PM ]

Fixed, https://github.com/clojure/core.match/commit/5e2762fbca6179b3b19505d7603fc6a37108dba1

No tests. The rule is never reorder - always return 1.





[MATCH-29] match should not throw, return nil if no match found like cond Created: 09/Oct/11  Updated: 28/Jul/13  Resolved: 10/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Comments   
Comment by David Nolen [ 10/Oct/11 10:55 PM ]

Fixed, https://github.com/clojure/core.match/commit/c9e47acfc7dd4364428cfe011476a3492787f050





[MATCH-56] IndexOutOfBoundsException when matching empty vector Created: 27/Mar/12  Updated: 28/Jul/13  Resolved: 16/Jun/13

Status: Closed
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: Completed 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.

Comment by David Nolen [ 16/Jun/13 10:08 PM ]

fixed http://github.com/clojure/core.match/commit/59df5b32b3c06b0038f76ccb88670fa9f42e5547





[MATCH-45] group types together Created: 21/Dec/11  Updated: 28/Jul/13  Resolved: 23/Dec/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

Currently if patterns of the same type are not adjacent, matching fails unexpectedly. This should always work. This does beg the question about things which might possible match multiple clauses. When we get to predicate dispatch we may check for subsumption. However in some cases we might have something which is legitimately both things. We haven't decided yet how we'll handle that.



 Comments   
Comment by David Nolen [ 23/Dec/11 10:09 PM ]

Fixed, https://github.com/clojure/core.match/commit/29607a2105d8af90c5b8d9d4cde9191e63a2570c





[MATCH-43] Vector pattern - unreachable clause Created: 10/Dec/11  Updated: 28/Jul/13  Resolved: 27/Dec/11

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

Type: Defect Priority: Major
Reporter: Benny Tsai Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None
Environment:

Clojure 1.3, core.match 0.2.0-alpha8



 Description   

This is the simplest example I could come up with:

(defn f [xs]
(match xs
[:a] "a"
[:b b] b
[:c] "c"
:else "problem!"))

[:a] and [:b b] can be matched with no problems, but [:c] can't be matched for some reason:

user=> (f [:a])
"a"
user=> (f [:b 1])
1
user=> (f [:c])
"problem!"



 Comments   
Comment by David Nolen [ 12/Dec/11 9:24 PM ]

This will have to wait for http://dev.clojure.org/jira/browse/MATCH-31. There are some deeper issues with vector pattern matching that need to get ironed out first.

In the meantime just put your [:c] test above [:b b]. The key idea is to keep vector patterns of the same size "together".

Comment by David Nolen [ 27/Dec/11 8:23 PM ]

fixed, https://github.com/clojure/core.match/commit/b2ee29d701a9306c1c494d91c371c01a512aee0c





[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: 28/Jul/13  Resolved: 20/Jun/13

Status: Closed
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: Completed Votes: 0
Labels: bug, seq
Environment:

with Clojure 1.3



 Description   

The following match throws:

(let [q '(a) y '(b) z '(c)]
  (match [q (seq y) z]
    [([_] :seq) _ _] 'a
    [_ _ _] 'b))

Looking at the macro expansion there's something clearly wrong simply with the fact that the seq expression occurs in multiple places instead of just at the beginning of the macro expansion.



 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]
...)

Comment by David Nolen [ 20/Jun/13 7:35 AM ]

fixed, http://github.com/clojure/core.match/commit/7b02b83478862a8fcaa3367871d043d4a40d9413





[MATCH-15] Binding issue Created: 22/Sep/11  Updated: 28/Jul/13  Resolved: 25/Sep/11

Status: Closed
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: Completed Votes: 0
Labels: None
Environment:

Latest HEAD version of match while compile my project https://github.com/narkisr/gitolite-webui/tree/match-fix



 Description   

The binding in the match macro used in gitolite-webui.notification 41:

(defn email-request [req]
(match [req]
[{:name _ :repo (r :when (comp not nil?)) :email email}] (notify-user-constrained email "Your repository access request has been approved" (<< "Verify that you can access it by cloning ~(:repo req) repository.") @config)
[{:name _ :key _ :email email}] (notify-user-constrained email "Your key request in gitolite was approved" (<< "Please verify that your public key matches ~(:key req)") @config)
))

Trying to create jar results with:

(match-fix)⚡ % lein uberjar ~/CodeProjects/gitolite-webui
Cleaning up.
WARNING: gitolite-webui.notification, line 42: Non-exhaustive pattern matrix, consider adding :else clause
Exception in thread "main" java.lang.Exception: Unable to resolve symbol: email in this context (notification.clj:43)
at clojure.lang.Compiler.analyze(Compiler.java:5205)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3057)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5371)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler$IfExpr$Parser.parse(Compiler.java:2315)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5369)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5357)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5357)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:4670)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:4328)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3173)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5367)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5357)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:798)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5369)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5357)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.access$100(Compiler.java:35)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:438)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5369)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler.compile1(Compiler.java:5928)
at clojure.lang.Compiler.compile(Compiler.java:5992)
at clojure.lang.RT.compile(RT.java:368)
at clojure.lang.RT.load(RT.java:407)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4519.invoke(core.clj:4915)
at clojure.core$load.doInvoke(core.clj:4914)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:4729)
at clojure.core$load_lib.doInvoke(core.clj:4766)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:542)
at clojure.core$load_libs.doInvoke(core.clj:4800)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:544)
at clojure.core$use.doInvoke(core.clj:4892)
at clojure.lang.RestFn.invoke(RestFn.java:512)
at gitolite_webui.persistency$loading_4414auto_.invoke(persistency.clj:1)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:2906)
at clojure.lang.Compiler.compile1(Compiler.java:5933)
at clojure.lang.Compiler.compile1(Compiler.java:5923)
at clojure.lang.Compiler.compile(Compiler.java:5992)
at clojure.lang.RT.compile(RT.java:368)
at clojure.lang.RT.load(RT.java:407)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4519.invoke(core.clj:4915)
at clojure.core$load.doInvoke(core.clj:4914)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:4729)
at clojure.core$load_lib.doInvoke(core.clj:4766)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:542)
at clojure.core$load_libs.doInvoke(core.clj:4800)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:542)
at clojure.core$require.doInvoke(core.clj:4881)
at clojure.lang.RestFn.invoke(RestFn.java:512)
at gitolite_webui.core$loading_4414auto_.invoke(core.clj:1)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:2906)
at clojure.lang.Compiler.compile1(Compiler.java:5933)
at clojure.lang.Compiler.compile1(Compiler.java:5923)
at clojure.lang.Compiler.compile(Compiler.java:5992)
at clojure.lang.RT.compile(RT.java:368)
at clojure.lang.RT.load(RT.java:407)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4519.invoke(core.clj:4915)
at clojure.core$load.doInvoke(core.clj:4914)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:4729)
at clojure.core$compile$fn__4524.invoke(core.clj:4926)
at clojure.core$compile.invoke(core.clj:4925)
at user$eval27.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:5424)
at clojure.lang.Compiler.eval(Compiler.java:5415)
at clojure.lang.Compiler.eval(Compiler.java:5391)
at clojure.core$eval.invoke(core.clj:2382)
at clojure.main$eval_opt.invoke(main.clj:235)
at clojure.main$initialize.invoke(main.clj:254)
at clojure.main$null_opt.invoke(main.clj:279)
at clojure.main$main.doInvoke(main.clj:354)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:369)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:482)
at clojure.main.main(main.java:37)
Caused by: java.lang.Exception: Unable to resolve symbol: email in this context
at clojure.lang.Compiler.resolveIn(Compiler.java:5677)
at clojure.lang.Compiler.resolve(Compiler.java:5621)
at clojure.lang.Compiler.analyzeSymbol(Compiler.java:5584)
at clojure.lang.Compiler.analyze(Compiler.java:5172)
... 100 more

Trying to use an else clause:

(defn email-request [req]
(match [req]
[{:name _ :repo (r :when (comp not nil?)) :email email}] (notify-user-constrained email "Your repository access request has been approved" (<< "Verify that you can access it by cloning ~(:repo req) repository.") @config)
[{:name _ :key _ :email email}] (notify-user-constrained email "Your key request in gitolite was approved" (<< "Please verify that your public key matches ~(:key req)") @config)
:else :error
))

Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalArgumentException: No method in multimethod 'to-source' for dispatch value: class clojure.core.match.core.WildcardPattern (notification.clj:42)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5376)



 Comments   
Comment by David Nolen [ 22/Sep/11 6:50 PM ]

Thanks! However, this is too much context. Please add an isolated case. This limits the moving parts as well as make it easy to add a new test case to handle your issue.

Comment by Ronen Narkis [ 23/Sep/11 3:59 PM ]

Hey David, iv created a single file project that reproduces this:

https://github.com/narkisr/MATCH_15

The single function in there is:

(defn email-request [req]
(match [req]
[{:name _ :repo (r :when (comp not nil?)) :email email}] (println email)
[{:name _ :key _ :email email}] (println email)
))

Running lein uberjar results with the same error.

Comment by David Nolen [ 25/Sep/11 7:53 PM ]

Turns out this only affected AOT code. We were doing some dynamic things that did not play well w/ AOT. Fixed in master, https://github.com/clojure/core.match/commit/64eb9d4ff8774c3f228cfa8958043a65c083ec86





[MATCH-57] Non deterministic match behavior for seqs when AOT Created: 05/Apr/12  Updated: 28/Jul/13  Resolved: 15/Jun/13

Status: Closed
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: Completed 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.

Comment by David Nolen [ 15/Jun/13 10:30 PM ]

This sounds very similar to the other AOT bug reported by Kevin Lynagh MATCH-53 which is fixed in master, unless I hear different this is resolved.





[MATCH-28] clojure.core.match ns instead of clojure.core.match.core Created: 09/Oct/11  Updated: 28/Jul/13  Resolved: 10/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Comments   
Comment by David Nolen [ 10/Oct/11 10:34 PM ]

Fixed, https://github.com/clojure/core.match/commit/af647a77415f5a8c8cc3d1222873b55f91241dde





[MATCH-30] throw if binding name reused in the same pattern row Created: 10/Oct/11  Updated: 28/Jul/13  Resolved: 19/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None

Attachments: Text File dup2.patch     Text File dup3.patch     Text File dup4.patch     Text File dup.patch    
Patch: Code and Test
Approval: Ok

 Comments   
Comment by Steve Miner [ 15/Oct/11 3:43 PM ]

Checks for duplicate wildcard names in a pattern row.

Comment by David Nolen [ 15/Oct/11 4:05 PM ]

You should be able to reuse bindings as is done in the red black tree pattern as there is no ambiguity there. If we can get that enhancement in I'll gladly accept this. Thanks for taking this on!

Comment by Steve Miner [ 16/Oct/11 3:53 PM ]

The new patch allows OR patterns to reuse wildcards, but still complains if there are other ambiguities. I added a couple of tests to illustrate.

Comment by David Nolen [ 17/Oct/11 10:33 AM ]

This looks good. It looks like you created this patch before I added your match-let. Mind creating a new version of this patch against HEAD? Thanks much.

Comment by Steve Miner [ 18/Oct/11 2:47 PM ]

Updated patch for latest HEAD

Comment by David Nolen [ 18/Oct/11 7:14 PM ]

I'm trying to apply with patch with git am, but I keep getting:

Applying: * src/main/clojure/clojure/core/match.clj: Add Stephen Miner's match-let
error: patch failed: src/main/clojure/clojure/core/match.clj:1532
error: src/main/clojure/clojure/core/match.clj: patch does not apply
Patch failed at 0001 * src/main/clojure/clojure/core/match.clj: Add Stephen Miner's match-let

It looks like the previous commit of my pasting of your match-let patch is mixed up into your latest patch.

Comment by Steve Miner [ 19/Oct/11 7:22 AM ]

Sorry, I made a git mistake with dup3.patch. I made a fresh patch called dup4.patch that should fix the problem.

Comment by David Nolen [ 19/Oct/11 9:57 AM ]

Fixed https://github.com/clojure/core.match/commit/819f7f7d874f63b74ba634a9bebc95da574d80eb





[MATCH-23] map pattern order bug Created: 03/Oct/11  Updated: 28/Jul/13  Resolved: 05/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

(let [x {:a 1 :b 2 :c 10 :d 30}]
(match [x]
[({:a _ :b _ :c _ :d _} :only [:a :b :c :d])] :a-1
[({:a _ :b 2} :only [:a :b])] :a0
[{:a 1 :c _}] :a1
[{:c 3 :d _ :e 4}] :a2
:else []))

returns :a1 instead of :a-1



 Comments   
Comment by David Nolen [ 05/Oct/11 9:39 PM ]

Fixed, https://github.com/clojure/core.match/commit/61e05362872d7f336e0c12c42765806a9e5b8fc4





[MATCH-68] Vector match "underflow" => IndexOutOfBoundsException Created: 22/Apr/13  Updated: 28/Jul/13  Resolved: 16/Jun/13

Status: Closed
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: Completed 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?

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

fixed, http://github.com/clojure/core.match/commit/302c355ebf751fa8dc442c8db8b901ebb4eacfae





[MATCH-41] This 5-clause match expression fails to compile Created: 30/Nov/11  Updated: 28/Jul/13  Resolved: 30/Nov/11

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

Type: Defect Priority: Major
Reporter: Gary Fredericks Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None
Environment:

Ubuntu 10.10

java version "1.6.0_20"
OpenJDK Runtime Environment (IcedTea6 1.9.10) (6b20-1.9.10-0ubuntu1~10.10.2)
OpenJDK 64-Bit Server VM (build 19.0-b09, mixed mode)



 Description   

This expression fails to compile with a NullPointerException. Oddly enough I seem unable to make it any more minimal:

(match [["foo"]]
    [["foo"]] :a0
    [["foo" a]] :a1
    [["baz"]] :a2
    [["baz" a b]] :a3)

When I included the SNAPSHOT release in my project that seemed to fix it, but oddly enough I cloned the git repo this morning and it was still broken on HEAD, so I have no idea what's going on.



 Comments   
Comment by David Nolen [ 30/Nov/11 8:12 PM ]

Fixed, https://github.com/clojure/core.match/commit/a790f7900da9152dcdf290ade34b8001c47869f1





[MATCH-54] Cannot AOT with certain match expression. Created: 04/Mar/12  Updated: 28/Jul/13  Resolved: 15/Jun/13

Status: Closed
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: Completed 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


 Comments   
Comment by David Nolen [ 15/Jun/13 10:33 PM ]

as far as I can tell this AOT bug is resolved in master





[MATCH-73] irrelevant binding at leaf nodes Created: 18/Jun/13  Updated: 28/Jul/13  Resolved: 19/Jun/13

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

Patterns emit useless bindings at the leaf node, only named wildcards and :as patterns should be emitted.



 Comments   
Comment by David Nolen [ 19/Jun/13 12:14 AM ]

fixed, http://github.com/clojure/core.match/commit/9afc9c6001f8a187b5611c4ac11877b049b071f4





[MATCH-37] remove match-1, match should support match-1 behavior Created: 28/Oct/11  Updated: 28/Jul/13  Resolved: 28/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

matching literal vectors is not something we support so there can be no ambiguity.



 Comments   
Comment by David Nolen [ 28/Oct/11 12:31 AM ]

Fixed, https://github.com/clojure/core.match/commit/5edc28c6cd5315818ec2a852e931f5b7fe7dff35





[MATCH-17] first-column-chosen-case Infinite Loop at Compilation Created: 25/Sep/11  Updated: 28/Jul/13  Resolved: 26/Sep/11

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

Type: Defect Priority: Major
Reporter: Ambrose Bonnaire-Sergeant Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None


 Description   

See: https://gist.github.com/1241625



 Comments   
Comment by David Nolen [ 26/Sep/11 5:48 AM ]

Fixed, https://github.com/clojure/core.match/commit/1b01e7fc6634e081f6a96db41eb65c91b95b8161





[MATCH-22] boolean expression fails Created: 01/Oct/11  Updated: 28/Jul/13  Resolved: 02/Oct/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

(match [false] [false] true) throws an error.

I thought I handled this case earlier, but seems like I missed something.



 Comments   
Comment by David Nolen [ 02/Oct/11 11:32 AM ]

Fixed, https://github.com/clojure/core.match/commit/66a36260eb77c1920f9db011cdb612d4797665a7





[MATCH-70] Matches against maps are treated as wildcards, even though they are not Created: 29/May/13  Updated: 28/Jul/13  Resolved: 15/Jun/13

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

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

Attachments: Text File 0001-Fixed-the-map-wildcard-issue.patch    
Patch: Code and Test

 Description   

The following tests fail:

(deftest map-pattern-match-bind-2
  (is (= (let [xqq {:cz 1 :dz 2}]
           (match [xqq]
             [{:z a :zz b}] [:a0 a b]
             [{:cz a :dz b}] [:a2 a b]
             :else []))
        [:a2 1 2])))

(deftest map-pattern-match-bind-3
  (is (= (let [xmm {:bz 2}]
           (match [xmm]
             [{:az a}] [:a0 a]
             [{:bz b}] [:a1 b]
             :else []))
        [:a1 2])))


 Comments   
Comment by David Nolen [ 29/May/13 8:26 PM ]

Thanks for the patch but this won't work - this defeats sharing tests. I'm looking into it.

Comment by David Pollak [ 29/May/13 10:38 PM ]

Thanks David. I was thinking about putting a "is this really a wildcard" flag on Wildcard and set it to false for Wildcards in MapPattern.

Anyway... if you want me to keep working on the issue, I'll be glad to. If my clumsy code and clumsy approach doesn't help... I'm down for sitting on the sidelines and watching you do the work.

Comment by David Nolen [ 30/May/13 12:35 AM ]

The issue is a bit trickier than it seems. core.match is written in a way such that we always try to share tests across patterns as much as possible. For example consider what happens with map patterns:

(match [x]
  [{:a _ :b 1}] ...
  [{:b _ :c 2}] ...)

In order to do optimal test sharing we expand the above into the following more or less (which is wrong):

:a :b :c
[_  1  _]
[_  _  2]

The problem here is that only the last element in the first row and the first element of the second row are true wildcards. Currently as you discovered the analysis doesn't consider the fact that the other wildcards really must be tested. So really we want something like the following:

:a    :b    :c
[V(_)  1     _]
[_     V(_)  2]

Here you can see we wrap the wildcard in a new pattern type - MapValuePattern. This will prevent the bad analysis.

I hope this makes sense - I've started implementing this and I don't think it will take me too long.

Just to make it a bit more clear imagine the following:

(match [x]
  [{:a _ :b _}] ...
  [{:b _ :c _}] ...)
:a    :b    :c
[V(_)  V(_)  _   ]
[_     V(_)  V(_)]

The wrapping now prevents the first row from being considered a row of wildcards.

Comment by David Nolen [ 02/Jun/13 11:33 AM ]

This should be fixed in master as of this commit http://github.com/clojure/core.match/commit/a07c2e9620df5b9d331bd6c380d47c15bf7cd60d

Let me know if it works for you.

Comment by David Pollak [ 02/Jun/13 1:00 PM ]

Awesome. Thanks! Please let me know when there are new JAR files in clojars.

Comment by David Nolen [ 15/Jun/13 10:30 PM ]

this has been resolved http://github.com/clojure/core.match/commit/a07c2e9620df5b9d331bd6c380d47c15bf7cd60d





[MATCH-63] IllegalArgumentException when AOT compiling namespace using clojure.core.match since alpha10 Created: 08/Aug/12  Updated: 28/Jul/13  Resolved: 15/Jun/13

Status: Closed
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: Completed 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?

Comment by David Nolen [ 15/Jun/13 10:38 PM ]

as far as I can tell, this is the same issue as MATCH-53 which is resolved in master. Unless I hear otherwise, I'm closing this one.





[MATCH-88] different semantics at runtime versus compile time Created: 27/Oct/13  Updated: 27/Oct/13  Resolved: 27/Oct/13

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

Type: Defect Priority: Major
Reporter: kovas boguta Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None


 Description   

((fn [x] (match x [1 1] 1 :else 2)) [1]) ->
2

(match [1] [1 1] 1 :else 2) ->
AssertionError Pattern row 1: Pattern row has differing number of patterns.



 Comments   
Comment by David Nolen [ 27/Oct/13 8:17 PM ]

This is not actually a bug, but perhaps an unfortunate side effect of a syntactic convenience. When using the vector syntax you not matching on a vector - just a list of local bindings. So in the first case you're matching a specific local binding, and in the second your matching a single value.





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

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

Type: Defect Priority: Minor
Reporter: Chas Emerick Assignee: Chas Emerick
Resolution: Declined 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)


 Comments   
Comment by David Nolen [ 02/Jun/13 11:39 AM ]

As it is this ticket is not useful. Chas can you add the minimal case? Thanks!

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

Without more details I'm inclined closed to this. I just need a minimal case and will be happy to investigate.

Comment by Chas Emerick [ 16/Jun/13 4:47 PM ]

I never was able to get a sane minimal case together. Later, I just coded around the problem, and all of the changes on master may make the issue moot at this point anyway. Closing.





[MATCH-32] Allow flattened pattern syntax at top-level to avoid nesting :when and :as Created: 12/Oct/11  Updated: 28/Jul/13  Resolved: 21/Oct/11

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

Type: Enhancement Priority: Minor
Reporter: Steve Miner Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File flat2.patch     Text File flat3.patch     Text File flat4.patch     Text File flat.patch    
Patch: Code and Test
Approval: Ok

 Description   

On the Clojure mailing list I wrote:

For guards, I wonder if the extra parens are really necessary. Couldn't the :when bind tightly to the previous pattern variable? Like Clojure FOR comprehensions. I think it would be easier to read that way. Same comment applies to :as. To cover the rare case of matching a literal :when or :as, you could quote it or use it as the first item in an OR pattern.

On Oct 10, 2011, at 3:11 PM, David Nolen wrote:

It would be nice to lose the extra parens - patch welcome



 Comments   
Comment by Steve Miner [ 12/Oct/11 10:35 AM ]

I attached a patch that groups the :when and :as terms appropriately given a "flattened" syntax. That is, [a :when even?] becomes [(a :when even?)] before being processed as usual. I only applied it to the top-level of the pattern row because I was concerned about recursive performance and things can get pretty complicated so maybe the magic isn't worth it.

Only :when and :as at the top level get any special treatment. No mangling for :seq or ::vector, etc. No mangling of nested patterns.

I also added a couple of tests for my changes.

Comment by Steve Miner [ 14/Oct/11 1:03 PM ]

I wrote an improved patch that should handle nested patterns as well. Still only groups :when and :as, not :seq since that seems sort of special.

Comment by Steve Miner [ 15/Oct/11 7:59 AM ]

Better to use seq? instead of list?

Comment by David Nolen [ 15/Oct/11 10:24 AM ]

At first glance this looks pretty neat! Will try to take a deeper look today. Thanks!

Comment by David Nolen [ 15/Oct/11 10:47 AM ]

One issue I have with this syntax enhancement - how does one match :when or :as as literals?

Comment by Steve Miner [ 15/Oct/11 3:13 PM ]

The patch tries to group the :when or :as if that makes sense. If it doesn't make sense [:when true nil], it leaves it alone so that would match the literal. In the rare case where it would be ambiguous, you would have to use a single OR pattern to get a literal match, such as [a (:when |) false]. I put something like that in one of my new tests.

Comment by Steve Miner [ 15/Oct/11 3:18 PM ]

By the way, it might be nice to allow a single element list to match that single pattern. That is, treat [(p)] the same as [p]. Right now, it's considered an error. It would also simply my patch, where I had to introduce interpose1 (as a variant of interpose) to handle an edge case with the OR pattern.

Comment by David Nolen [ 20/Oct/11 1:54 PM ]

I'm not a fan of (:when |). I'd prefer it if the patch included support for always matching literal keywords that are written as ':foo.

Comment by Steve Miner [ 20/Oct/11 3:04 PM ]

Revised patch to support ':when (and quoted keywords in general) to match the literal keyword. Updated against HEAD.

Comment by David Nolen [ 21/Oct/11 6:53 PM ]

Fixed, https://github.com/clojure/core.match/commit/d69abfaf68a86d5b9d73070e666720770779118f





[MATCH-60] Matching maps with :only broken in CLJS Created: 18/Jun/12  Updated: 28/Jul/13  Resolved: 01/Jul/12

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

Type: Defect Priority: Minor
Reporter: Kevin Lynagh Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File cljs_keyset.patch     Text File cljs_keyset.patch    
Patch: Code

 Description   

The `.keySet` method call doesn't exist on JavaScript objects.
Master throws compile errors on me, so I've attached a patch against alpha9 that removes the Java method call in favor of the pure Clojure `(set (keys m))`



 Comments   
Comment by David Nolen [ 18/Jun/12 10:49 AM ]

It would preferable to check the *clojurescript* dynamic var and do different emission. Thanks!

Comment by Kevin Lynagh [ 30/Jun/12 11:34 AM ]

Updated patch against master that uses clojurescript var. Also available at https://github.com/lynaghk/core.match/tree/60-cljs-keyset

Comment by David Nolen [ 01/Jul/12 11:03 AM ]

fixed, http://github.com/clojure/core.match/commit/cdeea55f211f1dbe4768c8aec3149bfcb00438a2





[MATCH-44] regroup-keywords should not use gensym Created: 12/Dec/11  Updated: 28/Jul/13  Resolved: 12/Dec/11

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

Type: Enhancement Priority: Minor
Reporter: Steve Miner Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File 0001-improved-regroup-keywords.patch    
Patch: Code

 Description   

I contributed the regroup-keywords function to allow 'flattened' match syntax for :when and :as. It used gensym to make a marker to simplify the algorithm. After seeing how other people had done similar things with sentinel values, I realized that (Object.) is a better unique value. Theoretically, an evil user could use the same symbol that the gensym had created. Also, it's better to test with identical? rather than = since the sentinel is unique. I will attach a patch with a slight refactoring.



 Comments   
Comment by David Nolen [ 12/Dec/11 9:30 PM ]

Fixed, https://github.com/clojure/core.match/commit/6d0f3fe33c4a85a12366d447e82cab59e299f94a





[MATCH-5] Rest patterns should infer their type Created: 04/Sep/11  Updated: 28/Jul/13  Resolved: 26/Sep/11

Status: Closed
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: Completed Votes: 0
Labels: None


 Description   

Rest patterns don't currently infer their type. A simple enhancement that would save some extra typing as well as potentially mysterious errors.



 Comments   
Comment by David Nolen [ 26/Sep/11 6:58 AM ]

Fixed, https://github.com/clojure/core.match/commit/d8e767948977837bfb138b9383d6f7c2d175c09e





[MATCH-3] strange infinite lazy seq of nils pattern rows bug at leaf nodes Created: 04/Sep/11  Updated: 28/Jul/13  Resolved: 25/Sep/11

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

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


 Description   

This is low priority, but should be investigated. To see this behavior just print out the pattern row at the leaf node cases. Encountered this while fixing symbol binding bug in vector patterns.



 Comments   
Comment by David Nolen [ 25/Sep/11 6:45 PM ]

Fixed, https://github.com/clojure/core.match/commit/7ceffec3876b5175f33182e75c91e2c8046a19e4





[MATCH-38] interpose1 no longer needed Created: 29/Oct/11  Updated: 28/Jul/13  Resolved: 29/Oct/11

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

Type: Enhancement Priority: Minor
Reporter: Steve Miner Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None


 Description   

With the fix for MATCH-34, the function interpose1 is no longer used and can be removed. It was there only to support the old infix OR pattern.



 Comments   
Comment by David Nolen [ 29/Oct/11 12:50 PM ]

Fixed, https://github.com/clojure/core.match/commit/314c665197bf6f74ed5e66518e93b48f5778ff60





[MATCH-48] Guards cannot be fn expressions Created: 10/Jan/12  Updated: 28/Jul/13  Resolved: 25/Feb/12

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

Type: Defect Priority: Minor
Reporter: Chris Gray Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File 0001-Added-new-multimethod-mutually-exclusive-inequality.patch     Text File 0001-Failing-test.patch     Text File 0002-Use-the-new-multimethod-and-add-some-tests.patch     File new-patches.diff    
Patch: Code and Test

 Description   

Anonymous function literals as guards (such as (a :when #(odd? %))) seem to confuse the match compiler. The attached test shows how.



 Comments   
Comment by David Nolen [ 10/Jan/12 10:04 PM ]

I'm on the fence about allowing inline fn expressions and fn literals as guards. The problem is that they can't be checked for equality and thus tests cannot be shared across guard patterns. I need to think about it some more but I don't consider this high priority in the near future. Any decision will have to take into consideration the goal of predicate dispatch.

Comment by Chris Gray [ 11/Jan/12 12:41 PM ]

Sorry, I think the fact that the functions in my earlier example were function literals was a bit of a red herring. The following test also fails.

(deftest guard-pattern-match-5
  (is (=
       (let [oddp odd?]
         (match [1 2]
                [a :when odd? b :when odd?] :a1
                [a :when oddp _] :a2
                [_ b :when even?] :a3
                :else :a4))
       :a2)))
Comment by David Nolen [ 11/Jan/12 12:44 PM ]

The earlier examples where not a red herring. This is likely a separate issue.

Comment by Chris Gray [ 11/Jan/12 12:50 PM ]

I really don't see how, given that there seems to be no code that specializes on the type of function given to a guard. My guess is that when guard-pattern-match-5 succeeds, guard-pattern-match-4 will succeed as well.

Comment by David Nolen [ 11/Jan/12 1:00 PM ]

Oh sorry you are right. This is exactly same problem. We can't know that odd? and oddp are the same. Again this is not something I'm interested in fixing without a lot more consideration.

Basically functions can't be tested for equality like types can. This means that the presence of a guard must create a backtrack point. However if we make guards work a little more like types (you have to declare them ahead of time) we lose a little bit of convenience but gain a lot of reasoning power and can share tests and avoid these pitfalls.

This discussion probably needs a design page.

Comment by Chris Gray [ 11/Jan/12 6:11 PM ]

Two more examples of the same problem, this time not using guards:

(deftest unequal-equal-tests
  (is (=
       (match ["foo" "bar"]
              [#".*" #"baz"] :a1
              [#"foo" _] :a2
              [_ "bar"] :a3
              :else :a4)
       :a2)))

(deftest unequal-equal-tests-2
  (is (=
       (let [a 1]
        (match [1 2]
               [(:or 1 2) 3] :a1
               [(:or 2 a) 2] :a2
               [1 _] :a3
               :else :a4))
       :a2)))
Comment by David Nolen [ 11/Jan/12 6:58 PM ]

They are not the same problem. These don't work for very different reasons. The first I probably won't even address and will leave for the community to deal with - I don't need robust pattern matching on regexes.

The second example is a legitimate bug around matching locals which is unrelated to this ticket. Feel free to open a new one for it.

Comment by Chris Gray [ 11/Jan/12 7:15 PM ]

Yes, you're right, the second is unrelated.

Comment by Chris Gray [ 12/Jan/12 11:20 AM ]

On further reflection, what all these examples show is that Maranget's algorithm is only correct for literals whose equality you can test at compile time. Thus, not even locals will work using his algorithm. Regexes and functions will certainly not work correctly 100% of the time.

What happens is that when multiple unequal tests in the same column can return a truthy value, you end up with a decision forest rather than a decision tree. If the first decision tree in the forest has the first and third end-states, while the second tree has the second end-state, if you end up in the third end-state, you must still check the second decision tree before you decide which end-state is actually correct.

This is a shame, since it means that compiling the matches becomes more complex. On the other hand, it seems like a great subject for a paper at programming-language conference, so there's always that.

On a serious note, though, this bug is major, and you should consider removing support for at least guards, locals, and regexes until it is fixed. The bugs that arise from it in the end-user's code are really hard to track down – it's as if `or` or `and` were broken 10% of the time.

Comment by David Nolen [ 12/Jan/12 11:29 AM ]

There is nothing wrong with Maranget's algorithm. We just have to be sure that we create a backtrack point - that's all.

Functions cannot be fixed because function equality is undecideable. So for guards we might create a backtrack point. I've already updated the README to describe what works at the moment. I have a branch which throws an error if :when is not given a vector of symbols or a symbol. It should probably be improved so that symbols are known top levels (no reassigning fns to locals).

Regex equality can probably be made to work but I'm not going to do it. (On further thought we can probably make patterns create backtrack points by default, can be overridden for those willing to make their patterns highly optimizeable)

Locals can be fixed, we'll definitely create a backtrack point for these.

Comment by Chris Gray [ 12/Jan/12 11:54 AM ]

I'm sorry, but this problem will not be solved by backtracking alone. At least not with the backtracking mechanism that currently exists.

With backtracking, you are still treating the problem as though you have a decision tree. A decision tree requires that all the tests at its nodes are mutually exclusive.

By assuming that you have a decision tree, once a match is found in the tree, that match is returned. As my last comment pointed out, that is not sufficient. You must also check to see if there is a match in an end-state that was declared earlier. I really don't see that that's possible given the current backtracking system.

Comment by David Nolen [ 12/Jan/12 1:26 PM ]

I don't follow you. Maranget's algorithm is not sufficient for pattern matching if we don't constrain columns to specific types. There are many things already in place to deal with the shortcomings of Maranget's approach given what we want to accomplish - for example, we actually have a grouping pass. This is the same approach that Racket uses as far as I can tell and they don't have any problems. Certainly none of the patterns you shown thus that far (besides fns exprs) pose any challenges that I can see.

Comment by Chris Gray [ 12/Jan/12 1:42 PM ]

Sorry, I was editing my comment as you made yours. I hope it is more clear now.

I guess I don't totally understand your code still, so I will try to rectify that before commenting again. From what I have seen, though, you are trying to build a decision tree. What I am saying is that isn't possible at compile time, since you can't ensure that the nodes of the tree are mutually exclusive.

Comment by David Nolen [ 12/Jan/12 1:51 PM ]

All known constructors are considered mutually exclusive. We group all constructors in a column preserving order as closely as possible. Decisions trees are created for these constructors. If we cannot know at compile time whether something is mutually exclusive (wildcards, locals), we create a backtrack point to handle them.

Consider that if we only have backtrack points (no trees) all tests could potentially be tried. Our approach is a hybrid one - we don't rely only on decisions trees and we don't rely only on backtracking.

When we get to integrating pattern matching on interfaces, protocols ambiguities of course become possibly. But even this can probably be handled reasonably with something like "prefers".

Comment by Chris Gray [ 12/Jan/12 3:07 PM ]

Consider the following pair of decision trees:

  1
 /
a
 \
  3*

  2*
 /
b--4*
 \
  5*

Where the numbers are the order in which the terminals appear, and they have stars beside them if they match. The correct terminal for core.match to return in this case is the second one. Currently, the code would return the third terminal. Suppose, however, that backtracking was added so that the tree rooted at b was checked for matches as well. This is certainly possible, though a lot of information would need to be kept about the match already found (which is what I meant about things not working with the current backtracking system). Also, you must ensure that the testing stops when you hit the second terminal, for two reasons – first, not doing so would imply that all terminals are checked, and second, the test to distinguish 4 from 5 could throw an exception. For similar reasons, the return value of the third terminal can't be computed – it could be a very long computation, or it could throw an exception.

Comment by David Nolen [ 12/Jan/12 3:28 PM ]

If the correct terminal is the second one, we will return the second one. No information needs to be kept around. I suggest you take a closer look at the code at this point.

Comment by Chris Gray [ 12/Jan/12 6:58 PM ]

Aah, you're right. (I think.) Might it be more accurate to say that the situation I proposed can't happen? That is, no two trees are created where there are lower-numbered terminals in the second tree than in the first tree?

Is the plan to add backtrack points for everything where equality can't be determined at compile time?

Comment by Chris Gray [ 12/Jan/12 11:27 PM ]

These patches implement the proper backtracking for tests that are not mutually exclusive.

Comment by David Nolen [ 13/Jan/12 9:15 AM ]

Wow, this is great. I've skimmed over the patches and they look pretty good. I will go over them more closely as soon as I can - there are a couple changes we should probably make. Thanks!

Comment by Chris Gray [ 13/Jan/12 11:08 AM ]

No problem. My apologies for the persistent misunderstanding.

Comment by David Nolen [ 14/Feb/12 4:39 PM ]

Sorry for the epic delay. Here are my notes on that patches:

1. Let's rename mutually-exclusive-inequality? to comparable?
2. I want GuardPatterns to comparable, I'm not going to support arbitrary fns - not worth it IMO.
As a compromise I'd be willing to rename :when patterns -> PredicatePatterns and GuardPatterns
can be allowed via :guard.
3. No need to declare OrPatterns as comparable - they aren't real patterns
4. No need to exclude VectorPatterns - the way that pattern matching works makes this unnecessary

If you make these changes I promise to apply these in a timely manner

Comment by Chris Gray [ 15/Feb/12 12:50 PM ]

Okay, patch uploaded. There is a fairly significant portion of it that is just cut and paste, which I'm not so happy about, but I don't think there's a way to do type inheritance, so I did the easier thing.

Comment by David Nolen [ 25/Feb/12 6:49 PM ]

Fixed, https://github.com/clojure/core.match/commit/ac92c6df3f70f56fbe12f9d3f46585e66102c50b

addressed MATCH-50





[MATCH-85] Locals don't work in core.async go blocks Created: 27/Jul/13  Updated: 30/Jul/13  Resolved: 30/Jul/13

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

Type: Defect Priority: Minor
Reporter: Michael Alyn Miller Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None
Environment:

clojure 1.5.1, core.match 0.2.0-rc5, core.async 0.1.0-20130726.150120-62



 Description   

Looks like the same problem described in MATCH-82 happens in both Clojure and ClojureScript if the match block is made from inside of a go block. For example:

(defn correct []
  (let [x 1]
    (match 2
      x 1
      _ 2)))

(defn incorrect []
  (go
    (let [x 1]
      (match 2
        x 1
        _ 2))))

(defn -main
  [& args]
  ;; "correct 2"
  (println "  correct" (correct))

  ;; "incorrect 1"
  (go (println "incorrect" (<! (incorrect))))
  (Thread/sleep 1000))


 Comments   
Comment by David Nolen [ 28/Jul/13 6:42 PM ]

This ticket needs more information, core.match and core.async provide pretty sophisticated macros so I'm not surprised that there may be some strange interactions between the two. core.async likely rewrites let statements and this probably interacts badly with locals matching.

Comment by David Nolen [ 30/Jul/13 12:23 PM ]

This is a core.async bug, http://dev.clojure.org/jira/browse/ASYNC-15





[MATCH-94] Make check-pattern message contents independent of Clojure hash function Created: 07/Feb/14  Updated: 21/Feb/14  Resolved: 21/Feb/14

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

Type: Enhancement Priority: Minor
Reporter: Andy Fingerhut Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: File match-94-v1.diff    

 Description   

The recent changes to Clojure's hash function have caused several test failures in libraries where the test results depended upon the seq order of a hash set or hash map. core.match is one of these, but fortunately it is only one test and easy to make the results independent of Clojure's hash function.



 Comments   
Comment by Andy Fingerhut [ 07/Feb/14 9:59 AM ]

Patch match-94-v1.diff simply calls sort on a list of symbols printed by check-pattern, so their order is independent of Clojure's hash fn.

With this change, core.match's tests all pass with the latest Clojure 1.6.0-master-SNAPSHOT

Comment by Andy Fingerhut [ 21/Feb/14 9:56 AM ]

Fix committed: https://github.com/clojure/core.match/commit/a379cbbe6fd3be394d0780c6ed2aa5b06f94d6fe





[MATCH-86] OrPattern (:or 1 2) cannot be aot-compiled Created: 01/Aug/13  Updated: 08/Apr/14  Resolved: 23/Sep/13

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

Type: Defect Priority: Minor
Reporter: Thomas Heller Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None
Environment:

core.match 0.2.0-rc5



 Description   

I have a match expression containing an (:or :x :y) and this seems to trip up AOT compilation when running "lein uberjar".

At least I get a

Exception in thread "main"
java.lang.IllegalArgumentException: No method in multimethod 'to-source' for dispatch value: class clojure.core.match.OrPattern

Works fine otherwise, just "lein uberjar" fails.



 Comments   
Comment by David Nolen [ 01/Aug/13 12:17 PM ]

hrm, I suspect that the Object multimethod cases are the source of the issue - these were eliminated from the group-pattern logic and many AOT issues evaporated. I'll think on this some.

Comment by David Nolen [ 23/Sep/13 7:56 PM ]

fixed, http://github.com/clojure/core.match/commit/ad7fa2097a1ed7f629f4d34a2c1e8d4a3af8eaa7

Comment by Anders Conbere [ 07/Apr/14 10:38 PM ]

Howdy,

Is it possible that this issues wasn't fixed by that commit?

I can reproduce on master by attempting to aot compile `clojure.core.match.test.core`. In fact, I can go back to when that commit was introduced and get the same error.

Steps to reproduce and patch to test with here: https://gist.github.com/aconbere/b9ce4b05b8bad1de6869

Comment by David Nolen [ 07/Apr/14 10:49 PM ]

AOT'ing tests adds more variables than I care to consider. Please demonstrate a reproducible bug in a minimal case, preferable a project that I clone and test against, thanks.

Comment by Zane Shelby [ 08/Apr/14 11:39 AM ]

Here's a Github project that reproduces the issue for me:

https://github.com/zane/core.match-bug/

Comment by David Nolen [ 08/Apr/14 12:11 PM ]

That is not the latest version of core.match. Please demonstrate that 0.2.1 has the issue.





[MATCH-33] typo in README.md Created: 20/Oct/11  Updated: 28/Jul/13  Resolved: 27/Oct/11

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

Type: Defect Priority: Trivial
Reporter: Steve Miner Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None


 Description   

Re: "As shown, :else clauses are special, in that they are not implicitely wrapped in []."

"implicitely" is misspelled, but "implicitly" would be the wrong word anyway as the intended meaning seems to be "explicitly". It would be clearer just to leave out the adverb.



 Comments   
Comment by David Nolen [ 27/Oct/11 11:19 PM ]

Fixed, https://github.com/clojure/core.match/commit/1399a77e7833abb3a41be538a6356bc3bd871152





[MATCH-91] One unit test always passes without testing anything Created: 23/Dec/13  Updated: 30/Dec/13  Resolved: 30/Dec/13

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

Type: Defect Priority: Trivial
Reporter: Andy Fingerhut Assignee: David Nolen
Resolution: Completed Votes: 0
Labels: None

Attachments: File match-91-v1.diff    

 Description   

This test is incorrectly parenthesized. It has the structure (is (= expr1) expr2), which always passes:

(deftest vector-rest-pattern-1
  (is (= (match [[:plus 1 2 3]]
           [[:pow arg pow]] 0
           [[:plus & args]] 1
           :else 2))
    1))

Another test named match-differing-patterns is repeated verbatim twice.



 Comments   
Comment by Andy Fingerhut [ 23/Dec/13 5:34 PM ]

Patch match-91-v1.diff fixes both of the issues mentioned in the description.

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

fixed https://github.com/clojure/core.match/commit/e3d2c9dff4645833c851fc366a6b7876c194a8f4





[MATCH-87] Bad interaction with core.async Created: 11/Sep/13  Updated: 01/Dec/13

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

Type: Defect Priority: Minor
Reporter: Stefan Fehrenbach Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: bug
Environment:

[org.clojure/core.async "0.1.0-SNAPSHOT"] (more specifically core.async-0.1.0-20130827.050117-78)
[org.clojure/core.match "0.2.0-rc5"]



 Description   

This prints "foo" as expected:

(defn works []
  (.log js/console
        (match ["qux" "foo"]
          ["qux" "bar"] 1
          ["qux" x]     x)))

This fails with an exception: Uncaught Error: No matching clause: ["qux" "foo"]
in up-to-date Chromium

(defn fails []
  (go
   (.log js/console
         (match (<! (go ["qux" "foo"]))
           ["qux" "bar"] 1
           ["qux" x]     x))))

I don't know either core.async nor core.match very well. My best guess is a undesired interaction between the nonlocal control flow for backtracking and the core.async state machine.

Note that this is a version of core.async where http://dev.clojure.org/jira/browse/ASYNC-15 is fixed.



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

This is not a bug, it's not possible to use <! outside of go blocks.

Comment by Stefan Fehrenbach [ 11/Sep/13 12:48 PM ]

Does that count as outside? Anyway, this should not be outside. Same problem.

(defn fails []
  (go (let [m (<! (go ["qux" "foo"]))]
        (.log js/console
              (match m
                ["qux" "bar"] 1
                ["qux" x] x)))))
Comment by David Nolen [ 11/Sep/13 1:17 PM ]

Sorry missed the surrounding go! However note tickets about interaction between core.match and core.async are extremely low priority without more information about whether the bug is actually in ASYNC or in MATCH. I just don't have the bandwidth to do that sort of investigation at the moment.

Still, thanks for the report.

Comment by Stefan Fehrenbach [ 11/Sep/13 2:05 PM ]

I see. I'm not so sure whether I should report this to ASYNC, any thoughts?
I'm not familiar with either library, but I'll try to investigate further when I have the time.
For now, I guess I'll do more stupid matching. It really is a shame, core.match is a perfect fit for dispatching on messages and channels coming from alts!. Anyways, thanks for your work!

Comment by David Nolen [ 30/Nov/13 2:28 PM ]

Is this still a problem? I think core.async recently added better analysis of the dot form.

Comment by Stefan Fehrenbach [ 01/Dec/13 2:45 AM ]

Hi, thanks for thinking about this. I got side tracked and did not look into it any further.
Unfortunately it still does not work.

Tested versions:
[org.clojure/clojurescript "0.0-2080"]
[org.clojure/core.async "0.1.242.0-44b1e3-alpha"]
[org.clojure/core.match "0.2.0"]





[MATCH-31] vector patterns should work on seq Created: 10/Oct/11  Updated: 24/Jun/13

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: 1
Labels: None


 Description   

This means abandoning subvec and using nth + offsets.






[MATCH-78] Switches on literals should happen via `case` not `cond` Created: 25/Jun/13  Updated: 25/Jun/13

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   

It worth investigating whether this improves performance at all.






[MATCH-79] Tidy up for 0.2.0, add comprehensive doc strings Created: 25/Jun/13  Updated: 25/Jun/13

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

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





[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-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-75] rest patterns don't work on arrays Created: 20/Jun/13  Updated: 20/Jun/13

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   

Currently they simply don't work. When we make it work we should probably wrap the array in something like ArraySeq. We might want to consider support for unwrapping ArraySeq. We need to carry type information as well as offset information.






[MATCH-74] pass occurrence to emit-pattern Created: 20/Jun/13  Updated: 20/Jun/13

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   

Currently we have a hack to read type information at vector pattern specialization time overriding whatever the :t field is for a VectorPattern instance. We should instead pass the occurrence to emit-pattern so the vector-pattern can start with the correct type information.






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

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.

Comment by Ron Pressler [ 10/Aug/13 4:57 PM ]

Hi. Any plans on resolving this?

Comment by David Nolen [ 11/Aug/13 10:55 AM ]

I have no specific timeline, it will definitely be after 0.2.0, only focusing on bugs at the moment.





[MATCH-90] ignore duplicate wildcard check if matching a local multiple times in same pattern row Created: 19/Nov/13  Updated: 19/Nov/13

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   
(let [v 10]
  (match x
    [v v v] ...))





[MATCH-93] Simple capturing of :or matches with :as doesn't work Created: 30/Jan/14  Updated: 30/Jan/14

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   

All three of these expressions should work (according to @dnolen in IRC):

user> (match/match [5] [((:or 5 6) :as x)] x)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context
user> (match/match [5] [(:or (5 :as x) (6 :as x))] x)
5
user> (match/match [5] [(:or (5 :as x) (6 :as y))] x)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context

(The first makes sense to me, but the latter two don't; e.g. should y be nil in the last example, or something else?)

Though it's not necessary, it'd be nice if the following "sugared" form worked, too:

user> (match/match [5] [(:or 5 6 :as x)] x)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context





[MATCH-95] recur detection logic is too naive Created: 16/Apr/14  Updated: 17/Apr/14

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   

The following explodes because of the presence of recur:

(defn rec [expr]
  (match expr
         [:global] 'GLOBAL
         [:constant x] x
         [:variable x] x
         [:lazy-variable x] `(deref ~x)
         [:if test if-true if-false] `(if ~(rec test)
                                        ~(rec if-true)
                                        ~(rec if-false))
         [:delist list index] `(get ~(rec list) ~(rec index))
         [:depair pair key] `(get ~(rec pair) ~(match key :first 0 :second 1))
         [:list elements] (map rec elements)
         [:fold-recur index-arg list-sym] `(recur (+ 1 ~index-arg) (rest ~list-sym))
         [:zip left right] `(map vector ~(rec left) ~(rec right))
         [:filter list arg body] `(filter (fn [~arg] ~(rec body) ~(rec list)))
         [:len list] `(count ~(rec list))
         [:pair first second] [(rec first) (rec second)]
         [:block arg body] `(fn [~arg] ~(rec body))
         [:app f arg] `(~(rec f) ~(rec arg))
         [:query e annotations] `(QUERY ~(rec e) ~annotations)
         [:lookup key] `(LOOKUP ~key)
         [:let name value expr] `(let [~name ~value] expr)
         ; ... about 15 more
         ))


 Comments   
Comment by Jeanine Adkisson [ 17/Apr/14 1:52 PM ]

A hacky workaround is to interpolate the 'recur symbol from an outer scope.

(def recur-sym 'recur)

(match expr
  ... `(~recur-sym ...))
Comment by David Nolen [ 17/Apr/14 1:58 PM ]

Now that tools.analyzer exists it won't be difficult to solve this properly.





[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-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-65] cata matching Created: 23/Nov/12  Updated: 15/Jun/13

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   

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






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

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





[MATCH-2] Matching Diagnostics Created: 04/Sep/11  Updated: 16/Jun/13

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   

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.

Comment by David Nolen [ 16/Jun/13 1:57 PM ]

Lowering priority. Happy to take a patch, but I don't think I'll be looking into this myself in the near future.





[MATCH-72] complexity analysis Created: 18/Jun/13  Updated: 18/Jun/13

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   

For smaller matches avoid backtracking actually greatly improves performance at the potential cost of code size. Perhaps we can devise a heuristic such that we employ the the best option available? Would need some serious hammock time.






[MATCH-89] perf 3x slower for ragged rows Created: 27/Oct/13  Updated: 28/Oct/13

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

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


 Description   

In both cases, match should fail immediately on seeing the first element.

Slow case:

(let [f
        (fn [x] (match x [1 1] 1 [2] 2 :else 3))]
    (time (dotimes [_ 100000] (f [3]))))
"Elapsed time: 57.899 msecs"

Fast case:

(let [f
        (fn [x] (match x [1 1] 1 [2 _] 2 :else 3))]
    (time (dotimes [_ 100000] (f [3]))))
"Elapsed time: 16.998 msecs"


 Comments   
Comment by David Nolen [ 27/Oct/13 8:24 PM ]

Ragged rows are hard to optimize. We used to try and intelligently group patterns - but this "optimization" created an incredible number of edgecase bugs. So until I or someone else can come up with a sound way to do this, going to continue to punt on this.

Comment by kovas boguta [ 28/Oct/13 6:03 PM ]

Can you point commit where that optimization existed? Just want to get a sense of what code path are affected.

Comment by David Nolen [ 28/Oct/13 9:08 PM ]

If you look at the repo tree around the first 0.2.0 alpha you'll see it, however the optimization was not global - it was a specific thing for each type of pattern. Again, I'm not particularly inclined to revisit this myself, but if you have a clever idea how it can be done without the previous problems I'm all for it.





[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 Apr 20 11:12:53 CDT 2014 using JIRA 4.4#649-r158309.