<< Back to previous view

[CLJ-1203] Fallback to hash-based comparison for non-Comparables in Util.compare() Created: 17/Apr/13  Updated: 29/Apr/13  Resolved: 29/Apr/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Tassilo Horn Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: enhancement, patch

Attachments: Text File 0001-Add-hasheq-based-fallback-to-Util.compare.patch    
Patch: Code

 Description   

I oftentimes use sorted collections, and my comparator functions usually look like that:

(fn [a b]
  (let [x (compare-according-to-my-use-case a b)]
    (if (zero? x)
       (compare a b)
       x)))

That is, I define the sorting order depending on the requirements of my use-case, and if that doesn't suffice to make a distinction, I simply fall back to the standard `compare` function in order to get a stable ordering anyhow. I think that's a widely used idiom, e.g., also used in "Clojure Programming" (for example page 109).

The problem with this approach is that several data structures don't implement Comparable, and thus aren't applicable to `compare` (you'll get a ClassCastException). Examples are maps, records, deftypes, and sequences.

The patch I'm going to attach extends `Util.compare()` with a fallback clause that performs a `hasheq()`-based comparison. This results in a meaningless but at least stable sorting order which suffices for use-cases like the one shown above.



 Comments   
Comment by Andy Fingerhut [ 18/Apr/13 9:01 PM ]

Patch 0001-Add-hasheq-based-fallback-to-Util.compare.patch dated Apr 17 2013 applies cleanly to latest master, but causes several unit tests in data_structures.clj to fail. These are the kinds of things you would expect to fail with the change made in the patch, because the failing tests expect an exception to be thrown when comparing objects that don't implement Comparable, and with this patch's changes they no longer do. If this patch's change is desired, those tests should probably be removed.

Comment by Tassilo Horn [ 19/Apr/13 2:34 AM ]

Thanks Andy, I can't believe I've forgotten to re-run the tests.

Anyway, I'm attaching a new version of the patch that deletes the few sorted-set and sorted-set-by invocations that check that an exception is thrown when creating sorted sets containing non-Comparables.

Comment by Tassilo Horn [ 19/Apr/13 2:35 AM ]

New version of the patch.

Comment by Andy Fingerhut [ 26/Apr/13 2:47 PM ]

Tassilo, you say that one of your use cases is sorted collections. Note that any compare function that returns 0 for two values will cause sorted sets and maps to treat the two compared values as equal, and at most one of them will get into the ordered set/map, the second treated as a duplicate, even though the values are not equal. See https://github.com/jafingerhut/thalia/blob/master/doc/other-topics/comparators.md#comparators-for-sorted-sets-and-maps-are-easy-to-get-wrong for an example (not based on your modified compare, but on a comparator that returns 0 for non-equal items).

With your proposed change to compare, this occurrence would become very dependent upon the hash function used. Probably quite rare, but it would crop up from time to time, and could potentially be very difficult to detect and track down the source.

Comment by Tassilo Horn [ 29/Apr/13 2:29 AM ]

Hi Andy, you are right. It's possible to add an explicit equals()-check in cases the hashcodes are the same, but I think there's nothing you can do in the hashcodes-equal-but-objects-are-not case. That is, there's no way to ensure the rule sgn(compare(x, y)) == -sgn(compare(y, x)), the transitivity rule, and the compare(x, y)==0 ==> sgn(compare(x, z))==sgn(compare(y, z)) for all z rule.

I'm closing that ticket.





[CLJ-1196] eval of defrecord instance with no fields produces {}, not itself Created: 10/Apr/13  Updated: 10/Apr/13  Resolved: 10/Apr/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Jason Wolfe Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Environment:

Mac OS X Clojure 1.5.1



 Description   

user> (defrecord Foo [])
user.Foo
user> (Foo.)
#user.Foo{}
user> (eval (Foo.))
{}

user> (defrecord Foo [a b])
user.Foo
user> (eval (Foo. 1 2))
#user.Foo{:a 1, :b 2}

As you can see, evaluating the record with no fields loses the type information. This came up in code that uses records to describe argument schema information for functions in a macro, with no direct use of 'eval'. It is unexpected because of the inconsistency between empty and non-empty defrecords, and because the Clojure docs say 'Any object other than those discussed above will evaluate to itself.'

http://clojure.org/evaluation

I'm happy to elaborate on the use case if there are questions.



 Comments   
Comment by Nicola Mometto [ 10/Apr/13 5:11 AM ]

I think this is a duplicate of http://dev.clojure.org/jira/browse/CLJ-1093

Comment by Jason Wolfe [ 10/Apr/13 10:51 AM ]

You are right, sorry for the duplication. I searched for empty record in JIRA and somehow missed that ticket.

Comment by Andy Fingerhut [ 10/Apr/13 11:42 AM ]

Close as duplicate of CLJ-1093.





[CLJ-1194] Typo in core.reducers Created: 08/Apr/13  Updated: 09/Apr/13  Resolved: 09/Apr/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Dmitry Groshev Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

As far as I can say, there is a typo in core.reducers (and therefore core.reducers/monoid is unusable in 1.5.1):

https://github.com/clojure/clojure/blob/master/src/clj/clojure/core/reducers.clj#L321

(fn m <-- this
    ([] (ctor))
    ([a b] (op a b))))

Should I submit a patch to fix this?



 Comments   
Comment by Ghadi Shayban [ 08/Apr/13 3:09 PM ]

I guess you didn't try to actually use the function to see if it is actually broken...

m is not a argument vector, those are below in the function clauses.

Comment by Dmitry Groshev [ 08/Apr/13 3:26 PM ]

I did, but as it turns out the error was somewhere else and I can't reproduce it within a "clean" environment. Sorry for this hasty ticket.

Comment by Andy Fingerhut [ 08/Apr/13 11:31 PM ]

Dmitry, do you think it is OK to close this ticket as declined, meaning no change will be made in response to it? I can do that for you, if you wish.

Comment by Dmitry Groshev [ 09/Apr/13 4:49 AM ]

Andy, I'll close it myself if you don't mind. I would done it earlier, but didn't have sufficient rights in JIRA.





[CLJ-1188] Public Java API Created: 30/Mar/13  Updated: 12/Apr/13  Resolved: 12/Apr/13

Status: Resolved
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.6

Type: Enhancement Priority: Major
Reporter: Stuart Halloway Assignee: Stuart Halloway
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File CLJ-1188.patch     Text File CLJ-1188-via-var-intern.patch     Text File CLJ-1188-wrapper-free.patch    
Patch: Code and Test
Approval: Ok

 Description   

Problem: Java consumers need an API into Clojure that does not drag in a ton of concrete implementation detail.

Solution: Very small API class that allows looking up Vars (returning IFn), and reading data (as edn). Uses Clojure logic where possible, e.g. Var.intern.

Current patch: CLJ-1188-via-var-intern.patch

Also considered:

  • wrapper class (inconvenient for users, wrappers anathema in Clojure)
  • common superinterface for IFn and Deref (unnecessary, might bloat vtable)

See also http://dev.clojure.org/display/design/Improvements+to+interop+from+Java



 Comments   
Comment by Kevin Downey [ 02/Apr/13 11:34 AM ]

the attached patch would turn

...
public static Var ENQUEUE = RT.var("greenmail.smtp","enqueue");
...
ENQUEUE.fn().invoke(userManager, state.getMessage());
...

in to something like

...
public static VRef ENQUEUE = API.vref("greenmail.smtp/enqueue");
...
ENQUEUE.fn().invoke(userManager, state.getMessage());
...

what is the value of VRefs over using Vars directly?

Comment by Kevin Downey [ 02/Apr/13 5:56 PM ]

using this from a java api, it looks like if the namespace the var is in is not loaded when you go to create a VRef it will return null, generally my java code that calls clojure looks something like

public static Var FOO = RT.var("namespace", "name");
public static NAMESPACE = Symbol.intern("namespace");
public static Var REQUIRE = RT.var("clojure", "require");

static {
  REQUIRE.invoke(NAMESPACE);
}

can you tell me without checking the java/jvm spec if FOO is null? does the static init block run before or after static fields are init'ed? returning null just seems like a bad idea.

Comment by Stuart Halloway [ 03/Apr/13 6:53 AM ]

Per discussion on the ticket and with Rich, the wrapper-free approach (Apr 3 patch) is preferred.

Comment by Stuart Halloway [ 03/Apr/13 7:03 AM ]

Hi Kevin,

The purpose of not returning Vars is outlined in the design discussion. That said, it is possible to return IFn, which does not drag in too much implementation detail (just a javadoc config tweak, see CLJ-1190). Today's patch returns IFn, which addresses the wrapper ickiness demonstrated by your code examples.

Java static initializers run in lexical order, and I trust Java programmers to know Java.

I can think of several options other than returning null when a var is not available, and they are all complecting, inconsistent with Clojure, or both.

Comment by Kevin Downey [ 03/Apr/13 12:08 PM ]

Hey,

Always returning the var is very consistent with clojure, it is what RT.var does. It is what the var lookups emitted by the compiler do. RT.var is most likely the point through which most java that calls clojure goes at the moment.

As to "hiding" vars, how about creating a clojure.lang.ILink interface with both deref() and fn(), have Var implement it. The previous discussion I see linked all seems to presume hiding Var without discussion of why it should be hidden. What I see Rich saying is:

So RT.var is the right idea. It would be nice to hide the Var class,
but unfortunately we can't make ClojureAPI.var() return both IFn and
IDeref without inventing a common subinterface. There are other
similar details.

and

We will need an interface unifying IDeref and IFn for the return type
of API.var()

It seems like Rich is suggesting that ILink or whatever should also bring in IFn, but I wonder if having a fn() that does the cast for you is an acceptable alternative to that.

Comment by Rich Hickey [ 12/Apr/13 8:24 AM ]

The API should be called var, not fn, and should return IFn. Also, I really want the logic of RT.var (i.e. Var.intern) to be used, not this new logic. Please find another way to handle the string/symbol support.





[CLJ-1179] distinct? does not accept zero arguments Created: 09/Mar/13  Updated: 12/Apr/13  Resolved: 12/Apr/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4, Release 1.5
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Jean Niklas L'orange Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: bug

Attachments: Text File clj-1179-distinct-zero-arguments.txt    
Patch: Code
Approval: Not Approved

 Description   

distinct? cannot be invoked with zero arguments. When using the pattern (apply distinct? x), this is bothersome as you have to check whether x is empty or not. It is also logical that distinct? should return true if no arguments are given, since there are no duplicates.

What (small set of) steps will reproduce the problem?

user=> (apply distinct? [])
ArityException Wrong number of args (0) passed to: core$distinct-QMARK-  clojure.lang.AFn.throwArity (AFn.java:437)

What is the expected output? What do you see instead?

I would expect distinct? to return true whenever given zero arguments.

What version are you using?

This was tested under Clojure 1.4 and Clojure 1.5.



 Comments   
Comment by Jean Niklas L'orange [ 09/Mar/13 6:08 AM ]

Attached the straightforward patch which solves this issue.





[CLJ-1178] Requiring the same ns doesn't throw an exception Created: 07/Mar/13  Updated: 29/Mar/13  Resolved: 29/Mar/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Michael Drogalis Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None

Approval: Not Approved

 Description   

The compiler will happily allow requiring the same ns twice. I can't see any reason you'd intentionally do this.

(ns program
  (:require [program.a :as a]
            [program.a :as b])

This caused some confusion for a while as to why b wasn't producing the expected functionality. Just a simple mistake that I think can be caught at compile time.



 Comments   
Comment by Stuart Halloway [ 29/Mar/13 5:57 AM ]

The example shows valid Clojure code.





[CLJ-1174] Website doc link for 1.4 api docs returns a 404 Created: 05/Mar/13  Updated: 05/Mar/13  Resolved: 05/Mar/13

Status: Resolved
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Ed O'Loughlin Assignee: Tom Faulhaber
Resolution: Completed Votes: 0
Labels: None
Environment:

All



 Description   

The API docs for Clojure 1.4 (http://clojure.github.com/clojure/branch-clojure-1.4.0/index.html), linked to from http://clojure.github.com/clojure/, returns a 404.

I logged it under this category because I can't see anywhere else to log bugs about clojure.org.



 Comments   
Comment by Tom Faulhaber [ 05/Mar/13 8:29 PM ]

Fixed. Thanks for pointing this out.





[CLJ-1173] One-arg protocol functions whose name begins in a dash generates a call to a wrong field in the emitted code Created: 01/Mar/13  Updated: 17/May/13  Resolved: 17/May/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Meikel Brandmeyer Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Environment:

Clojure 1.4



 Description   
(defprotocol P (-foo [this]))

This code generates a reflective call to a non-existing foo field instead of the correct -foo method.

I was told by Christophe Grand that changing the line 557 in core_deftype.clj from:

(. ~(with-meta target {:tag on-interface}) ~(or on-method method) ~@(rest gargs))

to

(. ~(with-meta target {:tag on-interface}) (~(or on-method method) ~@(rest gargs)))

is a quick fix. However I don't know too much about the compilation specifics of . to judge whether this is the correct fix.

Issue reproduction:

Clojure
user=> (set! *warn-on-reflection* true)
true
user=> (defprotocol P (-foo [this]))
P
Reflection warning, REPL:4 - reference to field foo can't be resolved.


 Comments   
Comment by Gabriel Horner [ 17/May/13 1:36 PM ]

CLJ-1202 addresses this exact issue with the same fix and includes tests





[CLJ-1170] conj-ing x on equal values should produce equal results Created: 23/Feb/13  Updated: 01/Mar/13  Resolved: 01/Mar/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Irakli Gozalishvili Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

I've recently have run into a WHAT behavior here is an example:

```clojure
(def head 1)
(def tail [2 3])

(= tail (rest (cons head tail))) ; true

;; Types don't really match but close enough I guess
(type tail) ; clojure.lang.PersistentVector
(vector? tail) ; true
(type (rest (cons head tail))) ; clojure.lang.PersistentVector$ChunkedSeq
(vector? (rest (cons head tail))) ; false

;; Bet then it get's ugly (I would expect them to be equal)
(= (conj tail :x) (conj (rest (cons head tail)) :x)) ; false

;; Because
(conj tail :x) ; [2 3 :x]
(conj (rest (cons head tail)) :x) ;(:x 2 3)
```

This brings me to a pretty surprising behavior, which is conj-ing
equal values produce non-equal results:

```clojure
(= '(2 3) [2 3]) ; true
(= (conj '(2 3) 1) (conj [2 3] 1))
```

I think conj should either produce equal results or list and vectors with
same elements should not be equal. That would also resolve a previous
problem, although intuitively I would expect `(rest (cons x y))` to
return `y` back.



 Comments   
Comment by Andy Fingerhut [ 24/Feb/13 10:46 AM ]

Irakli, it is an explicitly documented feature that conj puts new items in different places for lists (at the beginning) and vectors (at the end). rest is explicitly documented to call seq on its argument. See their doc strings.

I don't know if it is explicitly documented, or just long-standing practice, that vectors and seqs with the the same sequence of values in them are equal. I think that a lot of existing code would break if Clojure changed so those were not equal.





[CLJ-1168] Setting clojure.read.eval to unknown on JVM cmd line causes --eval option to fail Created: 19/Feb/13  Updated: 22/Feb/13  Resolved: 22/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

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

Attachments: Text File clj-1168-patch-v1.txt     Text File CLJ-1168-with-read-known.patch    
Patch: Code
Approval: Ok

 Description   

First discovered by Tim McCormack with Clojure 1.5.0-beta13 and -RC15:

$ java -Dclojure.read.eval=unknown -jar ~/.m2/repository/org/clojure/clojure/1.5.0-RC16/clojure-1.5.0-RC16.jar -e "(+ 1 2)"
Exception in thread "main" java.lang.RuntimeException: Reading disallowed - read-eval bound to :unknown

This would prevent a Leiningen user from putting the following line in their project.clj file in order to look for read or read-string calls that don't explicitly bind read-eval to true or false:

:jvm-opts ["-Dclojure.read.eval=unknown"]



 Comments   
Comment by Andy Fingerhut [ 19/Feb/13 7:42 PM ]

Patch clj-1168-patch-v1.txt dated Feb 19 2013 has been tested manually with these results:

% java -cp clojure.jar clojure.main

(ran some simple tests to ensure repl still works, and obeys -Dclojure.read.eval=unknown setting)

% java -Dclojure.read.eval=unknown -jar clojure.jar -e '(println (+ 1 2))'
3

Comment by Steve Miner [ 20/Feb/13 4:52 PM ]

The patch works for me, but I think it would be safer for the patch to treat *read-eval* :unknown as false for the purpose of -e. It's unlikely that anyone wants to -e '#=(boom)'. Also, there's no need for the let to capture the cur-read-eval. I suggest something like this for the patch (updated):

(defn- read-never-unknown [read-fn & args]
      (binding [*read-eval* (true? *read-eval*)]
         (apply read-fn args)))
Comment by Andy Fingerhut [ 21/Feb/13 6:10 AM ]

I have asked on the Leiningen email list whether treating read-eval :unknown as false for the purpose of -e would break Leiningen functionality, and will report back here when I find out.

Comment by Andy Fingerhut [ 21/Feb/13 3:02 PM ]

I don't have an answer from Leiningen folks yet, but I do have another thought related to Steve's comment:

The current behavior is to treat *read-eval* as true for the purposes of reading lines in the REPL, if -Dclojure.read.eval=unknown was specified on the command line. Why should expressions given after -e be any more restricted? Whoever is invoking the JVM has complete control.

If they really want *read-eval* to be false when reading the expressions after -e, just use -Dclojure.read.eval=false instead of =unknown.

Comment by Steve Miner [ 21/Feb/13 3:45 PM ]

You're right, the user has control. I was just thinking that the user might not appreciate the details and it would be safer to default to the false behavior. However, I failed to consider the REPL treatment – that's a good point.

In any case, the logic for the binding in the patch could be simplified. I think this would work for the intended result:

(defn- read-never-unknown [read-fn & args]
      (binding [*read-eval* (and *read-eval* true)]
         (apply read-fn args)))

Sorry, if my comments have descended into bike-shedding.

Comment by Stuart Halloway [ 22/Feb/13 9:00 AM ]

I implemented "with-read-known" patch after input from Rich. Helpers that establish bindings should take a closure or fn body, rather than carrying around explicit fns and arg lists as the original 19 Feb patch does.

Marking screened as of the Feb 22 with-read-known patch.

Comment by Tim McCormack [ 22/Feb/13 9:55 AM ]

Steve: More importantly, any time you call (eval (read ...)), there's no reason for *read-eval* to be anything other than true.

Comment by Tim McCormack [ 22/Feb/13 10:12 AM ]

Newer patch works. My verification procedure:

  • Patched master (should probably use an RC instead)
  • Compiled and installed (mvn install) with version = 1.5.0-clj1168 in pom.xml
  • Set up fresh Leiningen project including these options:
    :dependencies [[org.clojure/clojure "1.5.0-clj1168"]]
    :jvm-opts ["-Dclojure.read.eval=unknown"]
  • Verify: `lein repl` succeeds
    • Verify: => (read-string "foo") fails with "Reading disallowed - *read-eval* bound to :unknown"
    • Verify: => #=(+ 1 2) prints 3 (read is fully available to REPL)
  • Write -main fn in project as
    (defn -main [& args]
      (println *read-eval*)
      (println (read-string (first args))))
  • Verify: `lein run foo` prints :unknown and then fails with "Reading disallowed" error.
  • Bind *read-eval* to false in -main
  • Verify: `lein run foo` prints foo.




[CLJ-1166] Range function accumulates minor errors when called on floating-point numbers Created: 19/Feb/13  Updated: 29/Mar/13  Resolved: 01/Mar/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Stephen Nelson Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

Due to range's incremental computation minor errors introduced by floating point arithmetic accumulate, becoming more noticeable in long ranges and causing unexpected behaviour.

Compare the output of the following:

=> (range 0.0 10.0 0.1)
(0.0 0.1 0.2 0.30000000000000004 0.4 0.5 0.6 0.7 0.7999999999999999 0.8999999999999999 0.9999999999999999 1.0999999999999999 1.2 1.3 1.4000000000000001 1.5000000000000002 1.6000000000000003 1.7000000000000004 1.8000000000000005 1.9000000000000006 2.0000000000000004 2.1000000000000005 2.2000000000000006 2.3000000000000007 2.400000000000001 2.500000000000001 2.600000000000001 2.700000000000001 2.800000000000001 2.9000000000000012 3.0000000000000013 3.1000000000000014 3.2000000000000015 3.3000000000000016 3.4000000000000017 3.5000000000000018 3.600000000000002 3.700000000000002 3.800000000000002 3.900000000000002 4.000000000000002 4.100000000000001 4.200000000000001 4.300000000000001 4.4 4.5 4.6 4.699999999999999 4.799999999999999 4.899999999999999 4.999999999999998 5.099999999999998 5.1999999999999975 5.299999999999997 5.399999999999997 5.4999999999999964 5.599999999999996 5.699999999999996 5.799999999999995 5.899999999999995 5.999999999999995 6.099999999999994 6.199999999999994 6.299999999999994 6.399999999999993 6.499999999999993 6.5999999999999925 6.699999999999992 6.799999999999992 6.8999999999999915 6.999999999999991 7.099999999999991 7.19999999999999 7.29999999999999 7.39999999999999 7.499999999999989 7.599999999999989 7.699999999999989 7.799999999999988 7.899999999999988 7.999999999999988 8.099999999999987 8.199999999999987 8.299999999999986 8.399999999999986 8.499999999999986 8.599999999999985 8.699999999999985 8.799999999999985 8.899999999999984 8.999999999999984 9.099999999999984 9.199999999999983 9.299999999999983 9.399999999999983 9.499999999999982 9.599999999999982 9.699999999999982 9.799999999999981 9.89999999999998 9.99999999999998)

=> (defn range' [start end step] (map #(+ start (* % step)) (range 0 (/ (- end start) step) 1)))
=> (range' 0.0 10.0 0.1)
(0.0 0.1 0.2 0.30000000000000004 0.4 0.5 0.6000000000000001 0.7000000000000001 0.8 0.9 1.0 1.1 1.2000000000000002 1.3 1.4000000000000001 1.5 1.6 1.7000000000000002 1.8 1.9000000000000001 2.0 2.1 2.2 2.3000000000000003 2.4000000000000004 2.5 2.6 2.7 2.8000000000000003 2.9000000000000004 3.0 3.1 3.2 3.3000000000000003 3.4000000000000004 3.5 3.6 3.7 3.8000000000000003 3.9000000000000004 4.0 4.1000000000000005 4.2 4.3 4.4 4.5 4.6000000000000005 4.7 4.800000000000001 4.9 5.0 5.1000000000000005 5.2 5.300000000000001 5.4 5.5 5.6000000000000005 5.7 5.800000000000001 5.9 6.0 6.1000000000000005 6.2 6.300000000000001 6.4 6.5 6.6000000000000005 6.7 6.800000000000001 6.9 7.0 7.1000000000000005 7.2 7.300000000000001 7.4 7.5 7.6000000000000005 7.7 7.800000000000001 7.9 8.0 8.1 8.200000000000001 8.3 8.4 8.5 8.6 8.700000000000001 8.8 8.9 9.0 9.1 9.200000000000001 9.3 9.4 9.5 9.600000000000001 9.700000000000001 9.8 9.9)



 Comments   
Comment by Stephen Nelson [ 19/Feb/13 3:06 PM ]

=> (last (range 0.0 10000000.0 0.1))
9999999.98112945
=> (last (range' 0.0 10000000.0 0.1))
9999999.9

Comment by Stuart Halloway [ 01/Mar/13 10:08 AM ]

Range is incremental by design, and that is how floats work. Something with the desired behavior would need to be a different fn with a different name.

Comment by Stephen Nelson [ 03/Mar/13 2:38 PM ]

"Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step"

What specifically about that wording specifically suggests that the implementation will use naive increment-and-recurse behaviour? My reading is that the function will return a lazy sequence of numbers from start to end separated by step, not separated by 'almost step'.

This implementation leads to unexpected behaviour with bounds:

=> (count (range 0 100 1))
100
=> (count (range 0 10 0.1))
101

http://www.ima.umn.edu/~arnold/455.f96/disasters.html

Comment by Timothy Pratley [ 29/Mar/13 5:09 PM ]

range could avoid this issue cleanly by converting floats to bigdecimals (let me know if you think this is a good idea?)

I ran into this problem recently, and have to say it was pretty ugly. This is how I avoided the issue:

(defn rangef
"Returns a sequence of n numbers from start to end inclusive."
[start end n]
(for [i (range 0 n)]
(+ start (* i (/ (- end start) (dec n))))))

Hope that helps any disillusioned float users out there, or just pass in BigDecimals to range instead of floats... I would go so far as to say using floats with range as it stands is almost always going to end in tears (or worse as Stephen describes ).

Comment by Timothy Pratley [ 29/Mar/13 5:10 PM ]

[and just to be clear if it is considered an error, it would be nice if range explicitly forbade it]





[CLJ-1163] Updates to changes.md for Clojure 1.5.0-RC15 Created: 13/Feb/13  Updated: 13/Feb/13  Resolved: 13/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

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

Attachments: Text File update-changes-md-v1.txt    
Patch: Code

 Description   

Attached patch contains additional changes that have been made since late Oct 2012 up through Clojure 1.5.0-RC15. Also a few minor formatting tweaks to recently added section on edn reader.






[CLJ-1158] generative tests for read and edn/read Created: 09/Feb/13  Updated: 09/Feb/13  Resolved: 09/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Stuart Halloway Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File reader-tests.patch    
Patch: Code and Test
Approval: Ok

 Description   

This patch gets some generative read and edn/read roundtripping tests into the build, and the generators should serve as a basis for further extension. The patch is broken into three commits:

  • adopt the latest test.generative and data.generators, which have been enhanced to include generators more types (e.g. uuid, date, ratio)
  • tests
  • increase the duration of generative tests in the build

At the time I am posting this, test.generative 0.4.0 is not in Maven Central, so to build Clojure with this patch you will need to either wait on Central, or grab the latest test.generative bits, back up to the commit tagged 0.4.0, and mvn clean install test.generative.






[CLJ-1156] clojure.walk/stringifiy-keys does not stringify non-keyword keys Created: 03/Feb/13  Updated: 01/Mar/13  Resolved: 04/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Joel Kuiper Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None

Patch: None

 Description   

The doc says "Recursively transforms all map keys from keywords to strings." however only those keys that pass keyword? get transformed to string. This leaves other keys such as java.Long as-is.

A simple fix would be

(defn stringify-keys*
"Recursively transforms all map keys from keywords to strings."
[m]
(let [f (fn [[k v]] (if (keyword? k) [(name k) v] [(str k) v]))]
;; only apply to maps
(postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m)))



 Comments   
Comment by Andy Fingerhut [ 03/Feb/13 11:20 PM ]

It appears from the doc string that this function does exactly what it claims it will do, without any changes.

Comment by Joel Kuiper [ 04/Feb/13 4:29 AM ]

You're right.
Somehow I parsed the doc string wrongly. My sincere apologies! Can be marked invalid.

Comment by Andy Fingerhut [ 04/Feb/13 9:30 AM ]

Closing as declined, since submitter agrees that code behavior and documentation match.





[CLJ-1155] Suppress tracebacks from clojure.core Created: 01/Feb/13  Updated: 29/Mar/13  Resolved: 29/Mar/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Wilfred Hughes Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: enhancement

Attachments: Text File suppress_tracebacks.patch    
Patch: Code

 Description   

It would be really nice if we could hide the Java traceback from the compiler when it's not relevant. When there's no Java interop, it's not useful. I can't see any case where we want the tracebacks from the compiler referencing clojure.core.

Here's how a syntax error traceback looks at the moment on trunk:

$ more dodgy-map.clj
(defn dodgy-map []
  {:1 :2 :3})
$ java -cp target/clojure-1.5.0-master-SNAPSHOT.jar clojure.main dodgy-map.clj
Exception in thread "main" java.lang.RuntimeException: Map literal must contain an even number of forms, compiling:(/home/wilfred/src/clojure/dodgy-map.clj:2:13)
	at clojure.lang.Compiler.load(Compiler.java:7070)
	at clojure.lang.Compiler.loadFile(Compiler.java:7020)
	at clojure.main$load_script.invoke(main.clj:286)
	at clojure.main$script_opt.invoke(main.clj:348)
	at clojure.main$main$fn__6682.invoke(main.clj:432)
	at clojure.main$main.doInvoke(main.clj:429)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.lang.Var.invoke(Var.java:415)
	at clojure.lang.AFn.applyToHelper(AFn.java:161)
	at clojure.lang.Var.applyTo(Var.java:532)
	at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: Map literal must contain an even number of forms
	at clojure.lang.Util.runtimeException(Util.java:219)
	at clojure.lang.LispReader$MapReader.invoke(LispReader.java:1090)
	at clojure.lang.LispReader.readDelimitedList(LispReader.java:1145)
	at clojure.lang.LispReader$ListReader.invoke(LispReader.java:979)
	at clojure.lang.LispReader.read(LispReader.java:182)
	at clojure.lang.Compiler.load(Compiler.java:7058)
	... 10 more

With my patch, this is simplified to:

$ java -cp target/clojure-1.5.0-master-SNAPSHOT.jar clojure.main dodgy-map.clj
java.lang.RuntimeException: Map literal must contain an even number of forms, compiling:(/home/wilfred/src/clojure/dodgy-map.clj:2:13)

Another example: here's how name errors appear on trunk:

$ more i-dont-exist.clj
(defn no-such-variable []
  i-dont-exist)
$ java -cp target/clojure-1.5.0-master-SNAPSHOT.jar clojure.main i-dont-exist.clj
Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: i-dont-exist in this context, compiling:(/home/wilfred/src/clojure/i-dont-exist.clj:1:1)
	at clojure.lang.Compiler.analyze(Compiler.java:6380)
	at clojure.lang.Compiler.analyze(Compiler.java:6322)
	at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5708)
	at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5139)
	at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3751)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6558)
	at clojure.lang.Compiler.analyze(Compiler.java:6361)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6548)
	at clojure.lang.Compiler.analyze(Compiler.java:6361)
	at clojure.lang.Compiler.access$100(Compiler.java:37)
	at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:529)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6560)
	at clojure.lang.Compiler.analyze(Compiler.java:6361)
	at clojure.lang.Compiler.analyze(Compiler.java:6322)
	at clojure.lang.Compiler.eval(Compiler.java:6623)
	at clojure.lang.Compiler.load(Compiler.java:7063)
	at clojure.lang.Compiler.loadFile(Compiler.java:7020)
	at clojure.main$load_script.invoke(main.clj:286)
	at clojure.main$script_opt.invoke(main.clj:348)
	at clojure.main$main$fn__6682.invoke(main.clj:432)
	at clojure.main$main.doInvoke(main.clj:429)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.lang.Var.invoke(Var.java:415)
	at clojure.lang.AFn.applyToHelper(AFn.java:161)
	at clojure.lang.Var.applyTo(Var.java:532)
	at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: Unable to resolve symbol: i-dont-exist in this context
	at clojure.lang.Util.runtimeException(Util.java:219)
	at clojure.lang.Compiler.resolveIn(Compiler.java:6874)
	at clojure.lang.Compiler.resolve(Compiler.java:6818)
	at clojure.lang.Compiler.analyzeSymbol(Compiler.java:6779)
	at clojure.lang.Compiler.analyze(Compiler.java:6343)
	... 25 more

With patch:

$ java -cp target/clojure-1.5.0-master-SNAPSHOT.jar clojure.main i-dont-exist.clj
java.lang.RuntimeException: Unable to resolve symbol: i-dont-exist in this context, compiling:(/home/wilfred/src/clojure/i-dont-exist.clj:1:1)

I'm not familiar with the compiler internals, but I've attached a tentative patch. Undoubtedly it isn't perfect. For one, it would be nicer to say 'Syntax error' rather than 'java.lang.RuntimeException'. All the tests pass with this change.

Relevant mailing list discussion: https://groups.google.com/forum/?fromgroups=#!searchin/clojure/wilfred/clojure/M5NlEW7HJ_c/joUY6mo6Rd8J

Please let me know what you think. This would make my life easier when developing.



 Comments   
Comment by Stuart Halloway [ 29/Mar/13 6:06 AM ]

It is easy for tools that consume Clojure to hide stack traces for those who do not want to see them. If Clojure itself eats stack traces, it is impossible for those of us who do want to see them to get them back.

Please do this kind of work in tool (if at all) and make it optional for users.





[CLJ-1153] Change *read-eval* default value to false Created: 30/Jan/13  Updated: 01/Mar/13  Resolved: 09/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4, Release 1.5
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Andy Fingerhut Assignee: Unassigned
Resolution: Declined Votes: 33
Labels: None

Attachments: Text File clj-1153-patch-v2.txt     Text File CLJ-1185.patch    
Patch: Code
Approval: Not Approved

 Description   

Discussion on the security implications of read-eval defaulting to true here: https://groups.google.com/forum/?fromgroups=#!topic/clojure/qUk-bM0JSGc

I'm not sure whether the unit test that needs read-eval true in order to pass is a sign of lots of other code that would break if read-eval defaulted to false.



 Comments   
Comment by Phil Hagelberg [ 31/Jan/13 11:55 AM ]

It's worth noting that there was a breakin to rubygems.org over the weekend that was caused by what amounts to this same issue, but with YAML: https://news.ycombinator.com/item?id=5141138

The current default is both dangerous and undocumented; this needs to change.

Comment by Soren Macbeth [ 31/Jan/13 12:33 PM ]

Seconded!

Comment by Mike Anderson [ 01/Feb/13 12:52 AM ]

Thirded.

For what it's worth, on the topic of breaking changes I'd much rather my old code break than continue to work with an unnoticed security hole.

Comment by Stuart Halloway [ 01/Feb/13 7:21 AM ]

Fourthed. I hope folks will pitch in and help deal with any breakage.

Comment by Chas Emerick [ 01/Feb/13 12:57 PM ]

New patch attached, {{CLJ-1185.patch}}.

This patch eliminates the use of *print-dup* in the compiler entirely. read-string continues to be used to support values that can only be represented via tagged reader literals; I don't think there's any way around that, since the mapping between particular data readers and values' types are buried in individual print-method implementations.

All tests pass (including cases like (eval (list + 1 2 3)) as discussed in the ML thread referenced in the issue description), and a variety of sanity checks around evaluation and compilation tooling (e.g. AOT, nREPL, introspection utilities in Leiningen/Reply/Counterclockwise) all work as expected.

Of course, if this is applied, then any usage of read over trusted content containing #= forms will need to be done with *read-eval* bound to true.

To aid in testing, a Clojure build (1.5.0-RC4) + this patch is available here:

[com.cemerick/clojure "1.5.0-SNAPSHOT"]

Note that you'll have to exclude the standard Clojure dependency from your project in order for this one to take precedence; you can do this by adding

:exclusions [org.clojure/clojure]

to your project.clj.

Comment by Paul Stadig [ 01/Feb/13 2:49 PM ]

I ran the Sonian test base against this patch. I wouldn't say our test cases are comprehensive, but they're not trivial. We talk to databases through JDBC, and we deal with lots of different data types (BigInts, Strings, Dates, and such).

I had to make a few small changes to our code base, because we rely pretty heavily on print-dup to serialize non-user originated data. We have to add corresponding binding blocks when reading to set read-eval to true. Other than that, the tests all passed.

+1

Comment by Chas Emerick [ 01/Feb/13 4:28 PM ]

Thanks to all that have tested the patch! Looks like we've made some progress. I'm going to post to the main Clojure ML now and hopefully get more yay/nay votes.

Comment by Andy Fingerhut [ 02/Feb/13 11:05 AM ]

clj-1153-patch-v2.txt dated Feb 2 2013 is functionally identical to Chas Emerick's CLJ-1185.patch dated Feb 1 2013, and no retesting is needed by anyone because of it.

The only change I have made to his patch is: the doc string for read-eval now says its default value is false.

Comment by Andy Fingerhut [ 02/Feb/13 11:06 AM ]

Also removed my original didn't-fix-enough-things patch from Jan 30 2013.

Comment by Tim McCormack [ 02/Feb/13 3:22 PM ]

I'm bumping the Priority field from its default value to "Major" to reflect recent events. (I personally feel "blocker" would be more appropriate, or at least "critical", but I don't want to step on any toes.)

Comment by Rich Hickey [ 04/Feb/13 7:55 PM ]

https://github.com/clojure/clojure/commit/974a64c06917861b7557fd73154254195b2de548

Comment by Rich Hickey [ 09/Feb/13 9:17 AM ]

This ticket is an excellent example of a terrible ticket.

1) It does not lead with a problem statement. The title takes the form akin to "I want X". It proposes a tactic.

2) The description is woefully inadequate. Here too, no problem statement. Descriptions should point to any discussions, but discussions are long and rambling, and no substitute for a succinct problem statement in the description. Descriptions need to be maintained, with the current strategy and name of best patch.

3) No resolution strategy. Just patches attached. How is a reviewer supposed to assess your patch if you don't even bother stating what the problem is and what your approach will be in fixing it, how that approach does fix it, and what if any tradeoffs are being made?

4) The change being requested would be a breaking change. That should be made extremely clear in the description, and doubles the threshold for quality of motivation and implementation.

5) Any breaking change would have to carefully enumerate what would break and when, what the migration strategy would be etc.

6) The patch breaks the compiler. If you don't understand how the compiler works, and why features are there, you shouldn't submit patches that alter it. The only assessments made in comments are 'it works for me', which, while useful anecdotes, are insufficient.

While the ticket itself was bad, the uncritical rallying behind it was more troubling. This is not how Clojure was built, and will not be how it is maintained.

In the end, the ticket proposed a tactic, and that tactic has been rejected. Read safety has been addressed by other means.





[CLJ-1150] Make some PersistentVector, SubVector internals public Created: 19/Jan/13  Updated: 01/Mar/13  Resolved: 04/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Enhancement Priority: Major
Reporter: Michał Marczyk Assignee: Michał Marczyk
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File 0001-Make-some-PersistentVector-s-and-APersistentVector.S.patch    
Patch: Code
Approval: Ok

 Description   

This should help with RRBT-PV interop.






[CLJ-1145] thread-last can't accept 0 or 1 forms, thread-first can't accept 0 forms Created: 12/Jan/13  Updated: 13/Jan/13  Resolved: 13/Jan/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Víctor M. Valenzuela Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None


 Description   

At times, as the artifact of repl experimentation or a refactoring in progress, one wants to eval a threaded form with 1 or (less likely) 0 arguments.

(-> 42) ; fine
(->> 42) ; throws "ArityException Wrong number of args (1) passed to: core$-GT".

(->) ; throws "ArityException Wrong number of args (0) passed to: core$" (sic)
(->>) ; throws "ArityException Wrong number of args (0) passed to: core$-GT".

Apologies for the text rendering (how to cite code?).



 Comments   
Comment by Andy Fingerhut [ 12/Jan/13 3:29 PM ]

Is this a duplicate with CLJ-1086, CLJ-1121, or the combination of those two?

If arity 0 is a new aspect of this ticket, what would you expect the arity 0 versions to be transformed into? nil?

Comment by Víctor M. Valenzuela [ 12/Jan/13 6:46 PM ]

Surely a duplicate - but Jira's search couldn't find those! (used "->", "thread-last" etc as search queries).

While fairly unlikely to use / noisy to implement, the thing about feeding 0-arities to the threading macros is that they throw in exchange an unrelated exception rather than e.g. "ArityException Wrong number of args (0) passed to: core$->".

Don't know if this is simply how macros (can) work, but it called my attention.

Feel free to close my issue.

Comment by Andy Fingerhut [ 13/Jan/13 9:25 AM ]

I will go ahead and close this case as a duplicate. FYI, below is the behavior if the CLJ-1121 patch CLJ-1121-v002.patch and the CLJ-1083 patch CLJ-1083-attachments/better-throw-arity-messages.diff are both applied (the second one improves the error message in the 0-arity case):

Clojure 1.5.0-master-SNAPSHOT
user=> (->)
ArityException Wrong number of args (0) passed to: core/-> clojure.lang.Compiler.macroexpand1 (Compiler.java:6472)
user=> (-> 5)
5
user=> (->>)
ArityException Wrong number of args (0) passed to: core/->> clojure.lang.Compiler.macroexpand1 (Compiler.java:6472)
user=> (->> 5)
5

Comment by Andy Fingerhut [ 13/Jan/13 9:40 AM ]

The issue of a poor error message with 0-arity threading macros is improved by the patch attached to ticket CLJ-1083, and adding handling of the 1-arity case is improved by the patch attached to ticket CLJ-1121.





[CLJ-1140] {:as x} destructuring with an empty list raises exception Created: 30/Dec/12  Updated: 01/Mar/13  Resolved: 01/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Toby Crawley Assignee: Unassigned
Resolution: Completed Votes: 3
Labels: None

Attachments: File empty-list-destructuring-CLJ-1140-12.30.12.diff    
Patch: Code and Test
Approval: Ok

 Description   
user=> (clojure-version)
"1.4.0"
user=> (let [{:as x} '()] x)
{}

...

user=> (clojure-version)
"1.5.0-RC1"
user=> (let [{:as x} '()] x)
IllegalArgumentException No value supplied for key: null  clojure.lang.PersistentHashMap.create (PersistentHashMap.java:77)

The bug was introduced by a change[1] to support duplicate keys in map
destructuring. Using PersistentHashMap/create here introduces the above
bug, since it does not properly handle empty lists.

[1]: https://github.com/clojure/clojure/commit/93c795fe10ee5c92a36b6ec6373b3c80a31135c4



 Comments   
Comment by Toby Crawley [ 02/Jan/13 11:02 AM ]

There's been some discussion on clojure-dev around this issue: https://groups.google.com/d/topic/clojure-dev/qdDRNfEVfQ8/discussion

Comment by Toby Crawley [ 01/Feb/13 10:05 AM ]

An issue I brought up in the email thread is consistency: vector binding works with anything nthable, map binding works with anything associative. With my current patch (empty-list-destructuring-CLJ-1140-12.30.12.diff), only ISeqs are supported for kwarg map binding.

I'd prefer it work with anything seqable, and can provide a patch that does that. I would go ahead and do so, but now that this ticket is now Approval: OK, I didn't want to alter what had been OK'ed. Let me know if you want a patch that adds support for anything seqable.





[CLJ-1139] Compiler exception while compiling swank/commands/basic.clj Created: 23/Dec/12  Updated: 09/Feb/13  Resolved: 09/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Brian Rowe Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None
Environment:
  • Clojure: 1.5.0-RC1
  • Java: Java 1.7.0_05 Java HotSpot(TM) 64-Bit Server VM
  • Leiningen: 2.0.0-preview10
  • lein-swank: 1.4.4
  • lein-ritz: 0.6.0

Attachments: Text File tmp.txt    

 Description   

Current Behavior:

When attempting to start a swank server, the clojure compiler throws a CompilerException, and the process terminates.

Expected Behavior:

A swank server is successfully started.

Steps to reproduce (terminal session attached):

1. lein new tmp
2. Edit the project.clj to require clojure version 1.5.0-RC1
4. cd tmp
3. lein swank



 Comments   
Comment by Brian Rowe [ 23/Dec/12 4:58 AM ]

I suppose I should add that I'm using Mac OS X 10.8.2

Comment by Andy Fingerhut [ 24/Dec/12 9:27 AM ]

Have you noticed that swank-clojure [1] is deprecated, i.e. no longer under active development, and the developer recommends that you use nrepl.el [2] instead?

[1] https://github.com/technomancy/swank-clojure
[2] https://github.com/kingtim/nrepl.el

Comment by Andy Fingerhut [ 26/Dec/12 8:55 AM ]

It also appears that someone has created an update to lein-swank (to version 1.4.5) that works with Clojure 1.5.0-RC1:

https://groups.google.com/forum/#!topic/clojure/CAiajyDWJJg

(in particular Toby Crawley's post on Dec 26 2012)

Comment by Brian Rowe [ 08/Feb/13 8:03 PM ]

Yes, this can be closed.

Comment by Andy Fingerhut [ 09/Feb/13 2:20 AM ]

Submitter agrees this issue was resolved by changes in other software outside of Clojure.





[CLJ-1135] Add previous changelog items back to changes.md Created: 19/Dec/12  Updated: 02/Feb/13  Resolved: 02/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: Release 1.5

Type: Enhancement Priority: Trivial
Reporter: Cosmin Stejerean Assignee: Stuart Halloway
Resolution: Completed Votes: 1
Labels: None

Attachments: Text File add-changelog-items.patch    
Patch: Code
Approval: Vetted




[CLJ-1129] Invalid ns macro can yield a difficult to trace exception Created: 17/Dec/12  Updated: 19/Dec/12  Resolved: 19/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Howard Lewis Ship Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: aot, feedback


 Description   

I inadvertently stripped off the namespace part of my ns macro, so that it was (ns (:use .... Clearly a user error, but an easy one. However, the result (from the REPL or the AOT compiler) was not ideal:

Exception in thread "main" java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Named
	at clojure.core$name.invoke(core.clj:1489)
	at clojure.core$root_resource.invoke(core.clj:5210)
	at clojure.core$load_one.invoke(core.clj:5227)
	at clojure.core$compile$fn__4895.invoke(core.clj:5426)
	at clojure.core$compile.invoke(core.clj:5425)
	at clojuresque.tasks.compile$main$fn__64.invoke(compile.clj:23)
	at clojuresque.cli$with_command_line_STAR_.invoke(cli.clj:92)
	at clojuresque.tasks.compile$main.doInvoke(compile.clj:6)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invoke(core.clj:601)
	at clojure.lang.Var.invoke(Var.java:419)
	at clojuresque.Driver.main(Driver.java:39)

The problem here is that there is no indication of what file was being loaded and compiled at the time of the error. Since I was in the middle of refactoring a big swath of code, I had some work to do to track down which file I had mangled.

I would like to see a little more logging to the System/err to identify what resource file was being read and compiled by the compiler at the time of the exception.



 Comments   
Comment by Andy Fingerhut [ 18/Dec/12 1:12 AM ]

Howard, is this perhaps a duplicate of CLJ-939? Let me know, and I can close this ticket as a duplicate if so.

Comment by Howard Lewis Ship [ 18/Dec/12 11:10 AM ]

Yes, looks like a dupe to me. Sorry about that, I did do a search for existing issue before adding mine, but they can be hard to find.

Comment by Andy Fingerhut [ 19/Dec/12 1:09 AM ]

Closed as duplicate of CLJ-939.





[CLJ-1123] UNIX/Windows line endings - clojure.pprint tests cause failure in Windows build Created: 09/Dec/12  Updated: 10/Dec/12  Resolved: 10/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Mike Anderson Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: platform-specific, pprint
Environment:

Windows 7, Maven 3.0.4



 Description   

I ran a test build of the latest Clojure 1.5 master (372f03e) on Windows and found a number of failures in the "clojure.test-clojure.pprint" tests. All of these seem to be caused by incorrect assumptions about line endings. Example:

[java] {:clojure.test/vars (ns-macro-test),
[java] :thread/name "main",
[java] :pid 1528,
[java] :thread 1,
[java] :type :assert/fail,
[java] :level :warn,
[java] :test/actual
[java] (not
[java] (clojure.core/=
[java] "(ns slam.hound.stitch\r\n (:use [slam.hound.prettify :only [prettify]]))\r\n"
[java] "(ns slam.hound.stitch\n (:use [slam.hound.prettify :only [prettify]]))\n")),
[java] :test/expected
[java] (clojure.core/=
[java] (clojure.core/with-out-str
[java] (clojure.pprint/with-pprint-dispatch
[java] clojure.pprint/code-dispatch
[java] (clojure.pprint/pprint
[java] (clojure.core/read-string
[java] "(ns slam.hound.stitch\n (:use [slam.hound.prettify :only [prettify]]))"))))
[java] (clojure.core/str
[java] "(ns slam.hound.stitch\n (:use [slam.hound.prettify :only [prettify]]))"
[java] "\n")),
[java] :line 173,
[java] :tstamp 1355113319212,
[java] :file "test_pretty.clj"}

It isn't totally clear what the right behaviour should be: should pprint be producing platform specific line endings or not? Either way, the test should confirm the expected behaviour.



 Comments   
Comment by Andy Fingerhut [ 10/Dec/12 1:57 AM ]

Most likely this should be closed as a duplicate of CLJ-1076. The symptoms sound the same, and CLJ-1076 has a patch for it that should fix the problem.

Comment by Mike Anderson [ 10/Dec/12 2:03 AM ]

Hi Andy - yes this looks like a duplicate, thanks for spotting. Should be closed.

Comment by Andy Fingerhut [ 10/Dec/12 11:45 AM ]

Duplicate of CLJ-1076





[CLJ-1116] More REPL-friendly 'ns macro Created: 29/Nov/12  Updated: 01/Mar/13  Resolved: 11/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Laurent Petit Assignee: Unassigned
Resolution: Completed Votes: 3
Labels: None

Attachments: File dynamic-ns-patch2.diff    
Patch: Code
Approval: Ok

 Description   

The 'ns macro is not as dynamic as it could be.
For instance, the following line typed in a repl (ns a)(ns b (:require a)) currently (1.4, 1.3, etc.) fails with an exception because the (:require a) call tries to reach the filesystem for file a.clj or a__init.class.

The attached patch ( dynamic-ns-patch2.diff ) allows a successful call to (ns a) behave the same as a successful call to (require 'a), adding namespace a to the list of loaded-libs.

Discussion on googlegroup's mailing list: http://groups.google.com/group/clojure-dev/browse_thread/thread/fb231e6fab4a5ad



 Comments   
Comment by Rich Hickey [ 29/Nov/12 9:31 AM ]

screeners, please make sure this has tests before passing on

Comment by Laurent Petit [ 29/Nov/12 10:41 AM ]

Tests added

Comment by Timothy Baldridge [ 30/Nov/12 11:35 AM ]

Patch applies, fixes the bug. All tests pass.

Screened

Comment by Herwig Hochleitner [ 03/Dec/12 7:52 AM ]

I see this has already been screened, but FWIW I tested the repl with this patch and the behavior works for me.





[CLJ-1114] reify ignores :pre and :post Created: 25/Nov/12  Updated: 15/Dec/12  Resolved: 15/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Yongqian Li Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Approval: Not Approved

 Description   

reify ignores :pre and :post assertions

user=> ((reify clojure.lang.IFn (invoke [this] {:pre [false]} (println "hello"))))
hello
nil
user=> ((fn [this] {:pre [false]} (println "hello")) 0)
AssertionError Assert failed: false user/eval39/fn--40 (NO_SOURCE_FILE:13)

Expected exception to be thrown



 Comments   
Comment by Stuart Halloway [ 25/Nov/12 6:52 PM ]

reify is not documented to support these, so this should be classified as an enhancement

Comment by Timothy Baldridge [ 30/Nov/12 2:51 PM ]

Vetted.





[CLJ-1111] Loops returning primtives are boxed even in return position Created: 21/Nov/12  Updated: 22/Dec/12  Resolved: 22/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Christophe Grand Assignee: Christophe Grand
Resolution: Completed Votes: 3
Labels: None

Attachments: File prim-loop.diff    
Patch: Code
Approval: Ok

 Description   

Reported here: https://groups.google.com/d/topic/clojure/atoFzbyuyos/discussion

(defn first-bit?
  {:inline (fn [n] `(== 1 (clojure.lang.Numbers/and ~n, 1)) )}
  [^long n]
  (== 1 (clojure.lang.Numbers/and n, 1)))

(defn exp-int
  ^double [^double x, ^long c]
  (loop [result 1.0, factor x, c c]
    (if (> c 0)
        (recur
         (if (first-bit? c)
           (* result factor)
           result),
         (* factor factor),
         (bit-shift-right c 1))
      result)))

Last lines of the Java bytecode of `exp-int`:

59 dload 5;               /* result */
61 invokestatic 40;       /* java.lang.Double java.lang.Double.valueOf(double c) */
64 checkcast 85;          /* java.lang.Number */
67 invokevirtual 89;      /* double doubleValue() */
70 dreturn;

The compiler doesn't currently infer the primitive type as soon as there is a recur:

(use '[clojure.contrib.repl-utils :only [expression-info]])
(expression-info '(loop [a 1] a))
;=> {:class long, :primitive? true}
(expression-info '(loop [a 1] (if true a (recur a)))
;=> nil

Patch attached.



 Comments   
Comment by Stuart Halloway [ 25/Nov/12 7:12 PM ]

Tests pass, code looks reasonable. Would appreciate additional review.

Comment by Timothy Baldridge [ 26/Nov/12 10:59 AM ]

Tests also pass here. Looked through the code and played with a patched version of Clojure. I can't see a problem with it.

Comment by Christophe Grand [ 27/Nov/12 4:40 AM ]

FYI, gvec.clj has two loops which return primitives and thus was formerly boxed.





[CLJ-1110] let-> needs improvement Created: 20/Nov/12  Updated: 11/Dec/12  Resolved: 29/Nov/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Alex Nixon Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Approval: Not Approved

 Description   

The function clojure.core/let-> is suboptimal in a few regards:
1. It's name lends you to believe it is "let-like", but it is not - it does not take a binding form, and its arguments are 'backwards'
2. It's docstring doesn't make clear that it is intended for use solely in a threading-macro expression
3. It arbitrarily does not support destructuring, where it easily could.

Possible solutions:

  • rename it (e.g. to "bind->") to make clear it is not let-like
  • allow destructuring of the 'name' parameter

Google groups discussion: https://groups.google.com/d/topic/clojure/67JQ7xSUOM4/discussion



 Comments   
Comment by Yongqian Li [ 11/Dec/12 12:22 AM ]

Has it been decided whether as-> supports de-structuring or not? Right now it is inconsistent.

(as-> [0 1]
      [a b]
  [(inc a) (inc b)])

 => [1 2]



(as-> {:a 0 :b 1}
      {:keys [a b]}
  {:a (inc a) :b (inc b)})

 => {:keys [1 2]}
Comment by Yongqian Li [ 11/Dec/12 12:50 AM ]

Also, what about changing the name to >as? ->as reads like "pipeline as name", whereas as> implies that you are starting a new pipeline.

(-> 0
  (->as name 
    (...))

Makes it clearer that you are consuming a pipeline and the expressions within ->as are no longer being influenced by ->.

Comment by Yongqian Li [ 11/Dec/12 1:03 AM ]

Has the addition of ->>as been considered? That way you can use it inside a ->> like this:

(->> a 
  (->>as name
    (...)))

(-> a 
  (->as name
    (...)))

The signature would be [name forms init-expr].





[CLJ-1109] Oracle Java 5 fails to run tests when building Clojure Created: 19/Nov/12  Updated: 15/Dec/12  Resolved: 15/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Andy Fingerhut Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None
Environment:

Oracle Java 1.5.0_22, at least


Attachments: Text File patch-enable-java-5-to-pass-tests-v1.txt    
Patch: Code and Test
Approval: Not Approved

 Description   

This is due to the way that reducers.clj currently handles the ForkJoin library.



 Comments   
Comment by Andy Fingerhut [ 19/Nov/12 3:50 PM ]

Patch patch-enable-java-5-to-pass-tests-v1.txt dated Nov 19 2012 enables at least Oracle Java 1.5.0_22 to build and pass all tests in latest master.

No, tt doesn't implement a ForkJoin library. It simply declares some Clojure fj functions to throw an exception if they are called. In today's Clojure tests they never are.

Comment by Andy Fingerhut [ 20/Nov/12 3:45 PM ]

Updated patch with proper name and email address.

Comment by Timothy Baldridge [ 30/Nov/12 3:05 PM ]

IMO, more tests are always good. Vetted.

Comment by Rich Hickey [ 15/Dec/12 7:33 AM ]

This is the wrong approach to this problem. A better approach is to make reducers work even if no fj support is present by simply defining fold as sequential reduce in that case.





[CLJ-1106] Broken equality for sets Created: 09/Nov/12  Updated: 01/Mar/13  Resolved: 08/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4, Release 1.5
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Justin Kramer Assignee: Aaron Bedra
Resolution: Completed Votes: 4
Labels: None

Attachments: Text File 0001-CLJ-1106-Use-Util.hasheq-in-hashCode-for-persistent-.patch     Text File 0001-Fixing-set-equality.patch     File setequals.diff    
Patch: Code and Test
Approval: Ok

 Description   

Equality for sets is not consistent with other persistent collections when the hashCode differs:

(= {(Integer. -1) :foo} {(Long. -1) :foo})
=> true

(= [(Integer. -1)] [(Long. -1)])
=> true

(= #{(Integer. -1)} #{(Long. -1)})
=> false

Attached is what I believe to be a basic fix. It removes a hashCode check from APersistentSet.equals. A similar check was removed from APersistentMap in the following commit:

https://github.com/clojure/clojure/commit/b5f5ba2e15dc2f20e14e05141f7de7c6a3d91179

With this patch, set equality works as expected and all tests pass.

My understanding of the implications of this change are limited, so someone more knowledgeable would need to chime in about its correctness.



 Comments   
Comment by Andy Fingerhut [ 09/Nov/12 9:48 AM ]

Can you add some unit tests that fail with the current code but succeed with the change?

Comment by Justin Kramer [ 09/Nov/12 10:24 AM ]

Revised patch with unit test that fails in master and succeeds with patch

Comment by Timothy Baldridge [ 03/Dec/12 9:04 AM ]

vetting

Comment by Gary Fredericks [ 29/Jan/13 5:32 PM ]

This came up when we were trying to diff two datasets by putting them in sets and comparing. We had Integers because they came back from JDBC that way.

Comment by Aaron Bedra [ 29/Jan/13 5:35 PM ]

I'm going to take a look and try to get this shipped. It hit us and I would love to to see it in 1.5

Comment by Paul Stadig [ 29/Jan/13 7:14 PM ]

I applied the patch on master (ca465d6d) and it applied cleanly and fixes the issue.

Comment by Bo Jeanes [ 30/Jan/13 11:19 AM ]

Instead of removing m.hashCode() != hashCode(), perhaps we should use `Util.hasheq()` instead. It already seems to special case numbers (https://github.com/clojure/clojure/blob/f48d024e97/src/jvm/clojure/lang/Util.java#L164-L172) and won't have the potential performance impact that skipping hashCode checks could bring.

Comment by Bo Jeanes [ 30/Jan/13 11:39 AM ]

Attaching a patch with an alternate fix for this issue that does not skip hashCode checking.

It passes all existing tests and fixes this issue.

I want to benchmark the difference, too.

Comment by Bo Jeanes [ 30/Jan/13 1:32 PM ]

On further thought and comparison to APersistentMap, I'm not sure if that's the best use of Util.hasheq(). I can't find good reference on the semantic differences and am not familiar enough with the Clojure source to infer it, yet.

Comment by Aaron Bedra [ 02/Feb/13 12:33 PM ]

Bo, I don't see you listed on the contributors list. Did you send in a CA?

Comment by Aaron Bedra [ 02/Feb/13 1:36 PM ]

Both of the patches above are not complete. APersistentSet equiv calls equals. APersistentMap has two separate ways of handling this. This is the path that the fix should take.

Comment by Aaron Bedra [ 02/Feb/13 2:37 PM ]

This patch addresses the difference between equals and equiv.

Comment by Stuart Halloway [ 04/Feb/13 9:55 PM ]

The Set equality code currently in Clojure uses .hashCode to quickly bail out of comparisons in both .equals and .equiv. This feels wrong since .equals and .equiv presume different hashes. The map equality code avoids the problem by not checking any hash.

Aaron's 2/13 patch makes set equality work like map equality, not checking the hash. (I think a much shorter patch that accomplishes the same thing merely drops the call to hash.)

It seems to me a separate problem that both hash and set are broken for Java .equals rules, because of the equiv-based handling of their keys.

I think this needs more consideration.

Comment by Stuart Halloway [ 05/Feb/13 8:57 AM ]

Notes from discussion with Rich:

1. Aaron's 2/2/13 patch, which mimics map logic into set, is the preferred approach.

2. The broader issue I was worried about is the semantic collision between Map's containsKey and Associative's containsKey. This is out of scope here, and perhaps ever.

Comment by Aaron Bedra [ 05/Feb/13 9:38 AM ]

Any chance this will make 1.5?





[CLJ-1098] Extend CollFold and IKVReduce to nil Created: 31/Oct/12  Updated: 01/Mar/13  Resolved: 25/Jan/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Enhancement Priority: Minor
Reporter: Herwig Hochleitner Assignee: Unassigned
Resolution: Completed Votes: 3
Labels: None

Attachments: Text File 0001-CLJ-1098-Implement-IKVReduce-and-CollFold-for-nil.patch    
Patch: Code and Test
Approval: Ok

 Description   

Currently, reduce-kv and fold throw when used on nil, because their respective protocols don't extend to nil. This seems strange, since Clojure tends to handle nils gracefully where possible, especially in places where collections are expected.

See thread https://groups.google.com/d/topic/clojure/tGI8sIKQoh0/discussion



 Comments   
Comment by Herwig Hochleitner [ 31/Oct/12 8:44 PM ]

Attached patch with tests

Comment by Andy Fingerhut [ 14/Jan/13 11:04 AM ]

Another discussion thread: https://groups.google.com/forum/?fromgroups=#!topic/clojure/xPDDybYGvmc





[CLJ-1092] New function re-quote-replacement has incorrect :added metadata Created: 22/Oct/12  Updated: 22/Dec/12  Resolved: 22/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Andy Fingerhut Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File fix-added-metadata-for-re-quote-replacement.txt    
Patch: Code
Approval: Ok

 Description   

I created the patch for CLJ-870 that added the function re-quote-replacement before Clojure 1.4 was released, and I was apparently hoping it would get into that release. It is in now, but incorrectly states that fn re-quote-replacement was added in 1.4.



 Comments   
Comment by Andy Fingerhut [ 22/Oct/12 9:01 PM ]

And before creating this patch, I did a diff between Clojure 1.4 and 1.5-beta1 source code, and verified that every other function with :added metadata that has been added since 1.4 says "1.5". Only re-quote-replacement was mislabeled in this way.

Comment by Christopher Redinger [ 27/Nov/12 3:42 PM ]

As you'd expect, this patch applies cleanly and improves the correctness of the documentation.





[CLJ-1091] update changes.md to include 1.5 changes Created: 22/Oct/12  Updated: 11/Dec/12  Resolved: 11/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Task Priority: Major
Reporter: Stuart Halloway Assignee: Timothy Baldridge
Resolution: Completed Votes: 0
Labels: None

Attachments: File changes-draft-v10.md     File changes-draft-v11.md     File changes-draft-v5.md    
Approval: Ok

 Comments   
Comment by Andy Fingerhut [ 15/Nov/12 11:01 AM ]

changes-draft-v1.md is not a patch, but an outline of a proposed new changes.md file for Clojure 1.5 with some of the content fleshed out. It still has lots of occurrences of "TBD" for "To Be Documented" in it.

It does mention every ticket that had a patch committed since Clojure 1.4.0 until Nov 15 2012.

I am hoping someone who is more knowledgeable of the "TBD" parts takes this and runs with it.

Comment by Andy Fingerhut [ 22/Nov/12 7:16 PM ]

changes-draft-v2.md is very similar to the earlier changes-draft-v1.md described above, but has a few additions.

Comment by Timothy Baldridge [ 26/Nov/12 2:41 PM ]

V3 of the draft...should be almost good to go. Someone with more info on reducers should take a look at that section as have yet to actually use them much.

Comment by Andy Fingerhut [ 26/Nov/12 8:47 PM ]

Removed V2 of the draft as Timothy's V3 had all of it and more.

Comment by Timothy Baldridge [ 27/Nov/12 8:52 AM ]

Fleshed out the reducers section a bit.

Comment by Timothy Baldridge [ 27/Nov/12 8:53 AM ]

Alright, I think this is ready for a final review by someone besides me.

Comment by Christopher Redinger [ 28/Nov/12 12:48 PM ]

Editorial cleanup

Comment by Andy Fingerhut [ 28/Nov/12 12:56 PM ]

Christopher, isn't this file intended to be in Markdown format, not HTML?

Comment by Christopher Redinger [ 28/Nov/12 12:58 PM ]

uploading the correct md file

Comment by Andy Fingerhut [ 28/Nov/12 1:12 PM ]

changes-draft-v6.md same as v5, except for a couple of spelling corrections.

Comment by Timothy Baldridge [ 29/Nov/12 8:38 AM ]

Missing desc on when->. Fixed in v7 of the doc

Comment by Rich Hickey [ 02/Dec/12 6:37 PM ]

"1.1 Clojure 1.5 requires Java 1.6 or later"

did you mean "building Clojure 1.5"?

I don't know that anything requires 1.6

Comment by Rich Hickey [ 02/Dec/12 6:41 PM ]

test->, let-> when->

are now:

cond->, as-> and some->

Comment by Andy Fingerhut [ 02/Dec/12 6:49 PM ]

I'll put up an updated version soon, but that headline wasn't properly updated to match the later occurrence of it in the body, which is: "Clojure 1.5 reducers library requires Java 6 or later". Is it true that the ForkJoin library requires Java 6 or later? If not, how can it be made to work with Java 5?

Comment by Andy Fingerhut [ 02/Dec/12 8:42 PM ]

changes-draft-v8.md updates the table of contents headings to match those in the body, and updates names of new threading macros.

Comment by Steve Miner [ 03/Dec/12 9:40 AM ]

changes-draft-v8.md, section 2.4, needs an update for description of some->. The document says "logical true" where it should say "not nil". Same comment applies to some->>. The point is that false will thread through the forms. This is a change from the replaced when-> (in 1.5-beta1).

Comment by Timothy Baldridge [ 03/Dec/12 10:02 AM ]

updated to reflect changes to some-> and some->>

Comment by Steve Miner [ 03/Dec/12 10:15 AM ]

Sorry to nit pick, but there are two more "logical true" phrases in v9 that need to change to "not nil" in those some-> and some->> descriptions.

Comment by Timothy Baldridge [ 03/Dec/12 10:22 AM ]

Not a problem. Thanks for looking it over!

Comment by Stuart Halloway [ 03/Dec/12 1:30 PM ]

I find the following sentence a little vague: "Clojure 1.5 can still be compiled and run with Java 5, but the test suite will not pass due to the lack of support for ForkJoin."

The problem is the application of the "but" to both parts of the conjunction. Isn't the intent actually: "Clojure can run with Java version 1.5 or later. Running the Clojure build requires 1.6, in order to test features that work with ForkJoin."

Comment by Andy Fingerhut [ 03/Dec/12 1:52 PM ]

Stuart H, that is almost the intent, and probably close enough for this kind of documentation.

The full gory details are as follows:

Clojure can build and run with Java version 1.5 or later. A Java version 1.5 build of Clojure only works if you do not run the test suite, e.g. by using the command "ant jar". To build Clojure including running the test suite, or to use the new reducers library, requires Java 1.6 or later.

If the patch for CLJ-1109 is applied, the full gory details become simpler to state:

Clojure can build and run with Java version 1.5 or later. Using the new reducers library requires Java 1.6 or later.

Comment by Andy Fingerhut [ 03/Dec/12 1:59 PM ]

changes-draft-v11.md changes the description of Java 5 limitations to match the current gory details, and hopefully address Stuart H's concerns raised above.





[CLJ-1089] clojure.java.io/copy interprets read count of 0 as eos Created: 22/Oct/12  Updated: 22/Oct/12  Resolved: 22/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Herwig Hochleitner Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None

Attachments: Text File 0001-CLJ-1089-clojure.java.io-do-copy-methods-determine-e.patch    

 Description   

According to the interface http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#read()
InputStream.read() family of methods return -1 when the end of stream is reached.

do-copy methods currently use a test: (pos? size) to determine whether eos is reached. This mostly works, but the specification is pretty clear in that InputStream implementations are allowed to return reads of zero bytes before returning more bytes.

##EDIT changed title of ticket from "clojure.java.io/copy should test for -1 instead of 0 for end of stream"



 Comments   
Comment by Herwig Hochleitner [ 22/Oct/12 3:40 PM ]

Attached patch changes do-copy methods to test for -1

Comment by Andy Fingerhut [ 22/Oct/12 4:56 PM ]

Herwig, can you elaborate on "the specification is pretty clear in that InputStream implementations are allowed to return reads of zero bytes before returning more bytes"?

I ask because in the very InputStream documentation page you link to, it seems to explicitly say the opposite of what you claim: "If no byte is available because the stream is at the end of the file, the value -1 is returned; otherwise, at least one byte is read and stored into b."

Comment by Herwig Hochleitner [ 22/Oct/12 4:57 PM ]

I reread the spec for InputStream.read and it clearly says

"If no byte is available because the stream is at the end of the file, the value -1 is returned; otherwise, at least one byte is read and stored into b."

The reason I originally thought of this as an issue was a misbehaving ServletInputStream from Jetty.

I closed the issue as declined. Sorry for the noise!





[CLJ-1085] clojure.main/repl unconditionally refers REPL utilities into *ns* Created: 10/Oct/12  Updated: 20/Oct/12  Resolved: 20/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4, Release 1.5
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Chas Emerick Assignee: Unassigned
Resolution: Completed Votes: 3
Labels: None

Attachments: File CLJ-1085.diff     File CLJ-1085-refactor.diff    
Patch: Code
Approval: Ok

 Description   

A number of vars from clojure.repl, clojure.java.javadoc, and clojure.pprint are unconditionally referred into *ns* by clojure.main/repl. This is fine when it is being used e.g. as the primary driver of a terminal-bound Clojure REPL, but other usages can end up bringing those utility vars into namespaces other than 'user. This can cause problems if clojure.main/repl is used to drive a REPL within namespaces that already have referred or interned vars with the same names as those utility vars, e.g.:

$ java -jar ~/.m2/repository/org/clojure/clojure/1.5.0-alpha6/clojure-1.5.0-alpha6.jar
Clojure 1.5.0-alpha6
user=> (ns foo)
nil
foo=> (defn pp [] "hi!")
#'foo/pp
foo=> (pp)
"hi!"
foo=> (clojure.main/repl)
foo=> (pp)
nil
nil
foo=> (defn pp [] "whoops")
CompilerException java.lang.IllegalStateException: pp already refers to: #'clojure.pprint/pp in namespace: foo, compiling:(NO_SOURCE_PATH:7:1)

Worse, nREPL uses clojure.main/repl (in large part to maximize the consistency of REPL behaviour across different Clojure versions), where each user expression is evaluated through a separate clojure.main/repl invocation. This leads to the same problems as above, but for every nREPL user, session, and expression (reported @ NREPL-31).

A simple fix for this is to perform these refers only if *ns* is 'user (which, AFAICT, was the only intended effect of CLJ-310, CLJ-454, and https://github.com/clojure/clojure/commit/04764db, the changes that added these automatic implicit refers to clojure.main/repl).



 Comments   
Comment by Chas Emerick [ 10/Oct/12 1:36 PM ]

Patch attached to only refer in the utility vars if in the user namespace.

Comment by Steve Miner [ 10/Oct/12 2:03 PM ]

It would probably be better to test with ns-name (as opposed to comparing strings):

(= 'user (ns-name ns))

Comment by Kevin Downey [ 10/Oct/12 2:18 PM ]

I don't follow how it is required to call `clojure.main/repl` for every input

Comment by Chas Emerick [ 10/Oct/12 2:19 PM ]

Gah, of course. :-/ Patch updated.

Comment by Chas Emerick [ 10/Oct/12 2:32 PM ]

@Kevin: It's not required, but I found it far more straightforward to not try to pretend that the underlying transport was stream-based when it's actually message-based. It also means that sessions can be very lightweight: unless code is being evaluated within a session, it is not occupying a thread, and takes up only as much space as its map of thread-local bindings.

Comment by Chas Emerick [ 15/Oct/12 5:10 AM ]

Based on discussion on clojure-dev, I have attached an alternative patch ({{CLJ-1085-refactor.diff}}), which:

  • breaks out the libspecs specifying the implicit refers into their own var (so that they can be consistently applied by other REPL implementations)
  • moves the default require of the libspecs to be invoked only when REPL is started from clojure.main
Comment by Stuart Halloway [ 19/Oct/12 2:12 PM ]

Screened and liked the second "refactor" patch.





[CLJ-1084] (object-array [1]) is ~3x slower than (object-array (rseq [1])) Created: 09/Oct/12  Updated: 20/Oct/12  Resolved: 20/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Paul Stadig Assignee: Unassigned
Resolution: Completed Votes: 1
Labels: patch,

Attachments: Text File 0001-Make-PersistentVector-ChunkedSeq-implement-Counted.patch     Text File CLJ-1084-tests.patch    
Patch: Code and Test
Approval: Ok

 Description   

{{user=> (time (dotimes [_ 10000000] (object-array [1])))
"Elapsed time: 1178.116257 msecs"
nil
user=> (time (dotimes [_ 10000000] (object-array (rseq [1]))))
"Elapsed time: 422.42248 msecs"
nil}}

This appears to be because PersistentVector$ChunkedSeq does not implement Counted, so RT.count is iterating the ChunkedSeq to get its count.



 Comments   
Comment by Paul Stadig [ 09/Oct/12 2:11 PM ]

I don't believe this is Major priority, but I cannot edit the ticket after having created it.

Comment by Tassilo Horn [ 11/Oct/12 10:17 AM ]

This patch makes PersistentVector$ChunkedSeq implement Counted.

Performance before:

(let [v (vec (range 10000))
      vs (seq v)]
  (time (dotimes [_ 10000]
          (count v)))
  (time (dotimes [_ 10000]
          (count vs))))
;"Elapsed time: 0.862259 msecs"
;"Elapsed time: 7228.72486 msecs"

Performance after (with the patch):

(let [v (vec (range 10000))
      vs (seq v)]
  (time (dotimes [_ 10000]
          (count v)))
  (time (dotimes [_ 10000]
          (count vs))))
;"Elapsed time: 0.967301 msecs"
;"Elapsed time: 0.99391 msecs"

Also with Paul's test case.

Before:

(time (dotimes [_ 10000000] (object-array [1])))
;"Elapsed time: 1668.346997 msecs"
(time (dotimes [_ 10000000] (object-array (rseq [1]))))
;"Elapsed time: 662.820591 msecs"

After:

(time (dotimes [_ 10000000] (object-array [1])))
;"Elapsed time: 757.084577 msecs"
(time (dotimes [_ 10000000] (object-array (rseq [1]))))
;"Elapsed time: 680.602921 msecs"
Comment by Stuart Halloway [ 19/Oct/12 1:46 PM ]

Two patches to be applied together, the 10/19 patch adds tests and updates to latest test.generative.





[CLJ-1075] deftype: compiler error on set! for mutable field Created: 24/Sep/12  Updated: 03/Dec/12  Resolved: 03/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Gunnar Völkel Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None


 Description   

The following code demonstrates the error in a minimal example:

(defprotocol IBlob (do-sth [this, x]))

(deftype Blob [^{:volatile-mutable true} a]
  IBlob
  (do-sth [this, x] 
    (try (/ 1 x) 
      (catch Throwable t 
        (set! a (inc a))))
        (inc x)))

(deftype Blob2 [^{:volatile-mutable true} a]
  IBlob
  (do-sth [this, x] 
    (try (/ 1 x) 
      (catch Throwable t 
        (set! a (inc a))))))

Compiling Blob results in the following exception:

CompilerException java.lang.IllegalArgumentException: Cannot assign to non-mutable: a

Compiling Blob2 works as expected.



 Comments   
Comment by Chouser [ 24/Sep/12 9:13 AM ]
(defmethod print-method clojure.lang.Compiler$LocalBinding 
  [^clojure.lang.Compiler$LocalBinding o w]
  (.write w
    (str "#<LB "
      (binding [*print-meta* true]
        (pr-str {:sym (.-sym o)
                 :tag (.-tag o)
                 :idx (.-idx o)
                 :name (.-name o)
                 :isArg (.-isArg o)
                 :canBeCleared (.canBeCleared o)
                 :recurMistmatch (.-recurMistmatch o)})) ">")))

(defmacro prn-env []
  (doseq [[_ lb] &env]
    (prn lb)))

(deftype T [^:volatile-mutable x]
  clojure.lang.IDeref
  (deref [this]
    (try
      (catch Exception e
        (prn-env)
        (set! x 0)))
    1))

#<LB {:sym ^{:volatile-mutable true} x, :tag nil, :idx -1, :name "x", :isArg false, :canBeCleared true, :recurMistmatch false}>
#<LB {:sym e, :tag Exception, :idx 3, :name "e", :isArg false, :canBeCleared true, :recurMistmatch false}>
#<LB {:sym this, :tag compile__stub.user.T, :idx 0, :name "this", :isArg false, :canBeCleared true, :recurMistmatch false}>
CompilerException java.lang.IllegalArgumentException: Cannot assign to non-mutable: x, compiling:(NO_SOURCE_PATH:1)
Comment by Gunnar Völkel [ 24/Sep/12 9:21 AM ]

As a workaround you can create a setter method for that field, e.g.

(set-a [this, na] (set! a na))
Comment by Andy Fingerhut [ 24/Sep/12 10:06 AM ]

Is this the same issue as CLJ-1023?

Comment by Gunnar Völkel [ 04/Oct/12 4:15 AM ]

That one looks very similar, yes.
The "non-tail try-catch as closure" being the problem, would explain the examples above, as well.

Comment by Timothy Baldridge [ 03/Dec/12 10:52 AM ]

closing as duplicate of CLJ-1023





[CLJ-1071] ExceptionInfo does no abstraction Created: 17/Sep/12  Updated: 21/Sep/12  Resolved: 21/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Stuart Halloway Assignee: Unassigned
Resolution: Completed Votes: 1
Labels: None

Attachments: Text File clj-1071-iexceptioninfo.patch    
Patch: Code and Test
Approval: Ok

 Description   

There oughtta be an interface



 Comments   
Comment by Stuart Sierra [ 18/Sep/12 8:44 AM ]

Screened.

Comment by Fogus [ 18/Sep/12 8:46 AM ]

Looks fine to me.





[CLJ-1070] PersistentQueue's hash function does not match its equality Created: 15/Sep/12  Updated: 20/Oct/12  Resolved: 20/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Philip Potter Assignee: Philip Potter
Resolution: Completed Votes: 0
Labels: None

Attachments: File 001-fix-PersistentQueue-hash.clj     File 001-make-PersistentQueue-hash-match-equiv.diff     File 002-make-PersistentQueue-hash-match-equiv.diff    
Patch: Code and Test
Approval: Ok

 Description   

There are two issues:

1) PersistentQueue's hash function doesn't match its equiv function:

(def iq (conj clojure.lang.PersistentQueue/EMPTY (Integer. -1)))
(def lq (conj clojure.lang.PersistentQueue/EMPTY (Long. -1)))
[(= iq lq) (= (hash iq) (hash lq))]
;=> [true false]

2) PersistentQueue's hash function doesn't match PersistentVector's hash:

(def q (conj clojure.lang.PersistentQueue/EMPTY 1 2 3))
[(= [1 2 3] q) (= (hash [1 2 3]) (hash q))]
;=> [true false]



 Comments   
Comment by Philip Potter [ 15/Sep/12 1:52 PM ]

Clojure-dev discussion: https://groups.google.com/d/topic/clojure-dev/ME3-Ke-RbNk/discussion

Comment by Philip Potter [ 15/Sep/12 2:34 PM ]

Attached patch 001-make-PersistentQueue-hash-match-equiv.diff, 15/Sep/12.

Comment by Philip Potter [ 15/Sep/12 4:56 PM ]

Attached 002-make-PersistentQueue-hash-match-equiv.diff, 15/Sep/12. This patch supercedes 001-make-PersistentQueue-hash-match-equiv.diff.

Replaced test code which calls to Util/hasheq with code which calls hash instead.

This patch has a minor conflict with my patch for CLJ-1059, since they both add an interface to PersistentQueue (IHashEq here, List for CLJ-1059).

Comment by Chouser [ 18/Sep/12 1:38 AM ]

Thanks for the patch, Philip, it looks good to me.

It really is a pity the implementations of hashCode and hasheq are duplicated. I wonder how important it is to extend Obj? Regardless, that's the approach PersistentQueue was already taking, so changing that would be outside the scope of this ticket anyway.

I can't apply this patch with "git am", but "patch -p 1" works fine. I'm hoping this is a configuration problem on my end, so I'm marking this screened.





[CLJ-1069] data.priority-map has no artifacts information in the README Created: 14/Sep/12  Updated: 14/Sep/12  Resolved: 14/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Major
Reporter: Michael Klishin Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None


 Description   

data.priority-map README has no artifacts information and does not conform to the Contrib README standards in any way. Because clojure-dev is a closed group, I am filing it here



 Comments   
Comment by Andy Fingerhut [ 14/Sep/12 3:41 PM ]

This better belongs as a ticket for the JIRA project specifically for data.priority-map. It is here: http://dev.clojure.org/jira/browse/DPRIMAP

I have filed a ticket DPRIMAP-2 for that project, and will close this one.

You can find a complete list for all projects here: http://dev.clojure.org/jira/secure/BrowseProjects.jspa#all





[CLJ-1068] algo.monads README has no artifacts information Created: 14/Sep/12  Updated: 14/Sep/12  Resolved: 14/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Major
Reporter: Michael Klishin Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None


 Description   

algo.monads README has no artifacts information and does not conform to the Contrib README standards in any way. Because clojure-dev is a closed group, I am filing it here



 Comments   
Comment by Andy Fingerhut [ 14/Sep/12 3:38 PM ]

This better belongs as a ticket for the JIRA project specifically for algo.monads. It is here: http://dev.clojure.org/jira/browse/ALGOM

I have filed a ticket ALGOM-6 for that project, and will close this one.

You can find a complete list for all projects here: http://dev.clojure.org/jira/secure/BrowseProjects.jspa#all





[CLJ-1067] Fix error message inconsistencies in Symbol and Keyword Created: 14/Sep/12  Updated: 01/Mar/13  Resolved: 17/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Christoffer Sawicki Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None

Attachments: Text File Make-Keyword-extend-AFn-just-like-Symbol.patch    
Approval: Not Approved

 Description   

1. There are some ugly and unnecessary – but harmless – inconsistencies between Symbol and Keyword:

(.run 'foo);    => ArityException Wrong number of args (0) passed to: Symbol  clojure.lang.AFn.throwArity (AFn.java:437)
(.run :foo);    => UnsupportedOperationException   clojure.lang.Keyword.run (Keyword.java:97)
(.call 'foo);   => ArityException Wrong number of args (0) passed to: Symbol  clojure.lang.AFn.throwArity (AFn.java:437)
(.call :foo);   => IllegalArgumentException Wrong number of args passed to keyword: :foo  clojure.lang.Keyword.throwArity (Keyword.java:88)
(.invoke 'foo); => ArityException Wrong number of args (0) passed to: Symbol  clojure.lang.AFn.throwArity (AFn.java:437)
(.invoke :foo); => IllegalArgumentException Wrong number of args passed to keyword: :foo  clojure.lang.Keyword.throwArity (Keyword.java:88)

2. Keyword.java contains a lot of code that has already been factored out to AFn.java.

I propose that Keyword is modified to extend AFn to resolve the above issues.



 Comments   
Comment by Stuart Halloway [ 17/Sep/12 7:03 AM ]

At first glance, it appears that there could be some code sharing here. But the attached patch changes the semantics of run, which is a non-starter.

Comment by Christoffer Sawicki [ 17/Sep/12 7:19 AM ]

The only thing that changes is the type of thrown exception.

Current call tree:

Keyword.run() -> throw new UnsupportedOperationException()

Call tree with patch applied:

Keyword.run() -> AFn.run() -> AFn.invoke() -> AFn.throwArity(0) -> throw new ArityException(...)

(I.e. Keyword.run() always throws an exception, with and without my patch.)





[CLJ-1066] No dependency on jsr166y Created: 11/Sep/12  Updated: 20/Oct/12  Resolved: 20/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Wolodja Wentland Assignee: Stuart Halloway
Resolution: Completed Votes: 4
Labels: patch
Environment:

$ java -version
java version "1.7.0_03"
OpenJDK Runtime Environment (IcedTea7 2.1.2) (7u3-2.1.2-2)
OpenJDK 64-Bit Server VM (build 22.0-b10, mixed mode)
$ lein version
Leiningen 2.0.0-preview10 on Java 1.7.0_03 OpenJDK 64-Bit Server VM


Attachments: Text File 0001-Don-t-AOT-compile-clojure.core.reducers.patch    
Patch: Code
Approval: Ok

 Description   

The Clojure 1.5.0-alpha4 jars that have been deployed to maven.org seem to have been compiled against JDK6 which causes
an exception if one tries to use reducers/fold.

— snip —
Setup:

user=> (require '[clojure.core.reducers :as r])
nil
user=> (def v (vec (range 10000)))
#'user/v

;; JDK7 + clojure 1.5.0-alpha4 from maven.org
;; → :dependencies [[org.clojure/clojure "1.5.0-alpha4"]] in project.clj

user=> (r/fold + (r/map inc v))
ClassNotFoundException jsr166y.ForkJoinTask java.net.URLClassLoader$1.run (URLClassLoader.java:366)

;; JDK7 + clojure 1.5.0-alpha4 from maven.org
;; → :dependencies [[org.clojure/clojure "1.5.0-alpha4"]
;; [org.codehaus.jsr166-mirror/jsr166y "1.7.0"]]

user=> (r/fold + (r/map inc v))
50005000

;; JDK7 + clojure 1.5.0-alpha4 locally compiled (mvn install) against OpenJDK7
;; → :dependencies [[org.clojure/clojure "1.5.0-alpha4"]] in project.clj

user=> (r/fold + (r/map inc v))
5000050000
— snip —

It would be wonderful if this issue could be fixed before the release of 1.5.0.

Have a nice day

Wolodja



 Comments   
Comment by Tassilo Horn [ 12/Sep/12 9:44 AM ]

That's really a nasty problem. I wrote the code that makes it possible to compile clojure with either a JDK7 and native ForkJoin or an older JDK + jsr166y. Unfortunately, if you build clojure with a JDK7, reducers' fold requires a JDK7 at runtime, and if you build clojure with a JDK <7 + jsr166y, fold also requires jsr166y at runtime.

The essential problem is that clojure is AOT-compiled to class-files and those are put into the release jars. Ordinary clojure libraries are distributed as jar files containing clj files that are compiled when loaded. There, the implemented approach works just fine. For example, again your example with 1.5.0-alpha4:

;; 1.5.0-master4 compiled with JDK6 + jsr166y running on a JDK7
user=> (require '[clojure.core.reducers :as r])
nil
user=> (def v (vec (range 10000)))
#'user/v
user=> (r/fold + (r/map inc v))
ClassNotFoundException jsr166y.ForkJoinTask  java.net.URLClassLoader$1.run (URLClassLoader.java:366)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Now load the reducers.clj source code again, so that it
;; picks the right ForkJoin-impl for the current platform
(load-file "/home/horn/Repos/clj/clojure/src/clj/clojure/core/reducers.clj")
nil
user=> (r/fold + (r/map inc v))
50005000

So IMO, the best thing we can do is to omit AOT-compilation for reducers but to include only its clj file so that it'll be compiled automatically on the platform it eventually runs.

Comment by Tassilo Horn [ 12/Sep/12 11:55 AM ]

This patch removes the clojure.core.reducers namespace from the namespaces to be AOT compiled. So now this namespace will be JIT-compiled when being required, and at that point either the JDK7 ForkJoin classes or the jsr166y classes need to be there.

Comment by Stuart Halloway [ 21/Sep/12 1:31 PM ]

Rich: what is the right approach here?





[CLJ-1065] Allow duplicate set elements and map keys for all set and map constructors Created: 08/Sep/12  Updated: 04/Oct/12  Resolved: 04/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Andy Fingerhut Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File clj-1065-do-map-constant-duplicate-key-checks-compile-time-only-v1.txt     Text File clj-1065-set-map-constructors-allow-duplicates-v2.txt    
Patch: Code and Test
Approval: Ok

 Description   

See description here http://dev.clojure.org/display/design/Allow+duplicate+map+keys+and+set+elements



 Comments   
Comment by Andy Fingerhut [ 08/Sep/12 1:19 AM ]

I think that clj-1065-set-map-constructors-allow-duplicates-v1.txt dated Sep 7 2012 updates Clojure for the behavior Rich recommends on the dev Wiki page in the description. I may have missed something, though. Perhaps the most questionable part is the way I've chosen to implement array-map always taking the last key's value. It is no less efficient than the PersistentArrayMap createWithCheck method, i.e. O(n^2).

Comment by Rich Hickey [ 08/Sep/12 7:10 AM ]

Thanks!

array-map is ok. I would prefer that the docs strings say "as if by repeated assoc" (or conj for sets). "eliminates" and "last" are less precise e.g. what if you pass equal things, but with different metadata, to hash-set? "Eliminates dupes" doesn't say.

Comment by Andy Fingerhut [ 08/Sep/12 3:39 PM ]

clj-1065-set-map-constructors-allow-duplicates-v2.txt dated Sep 8 2012 supersedes yesterday's -v1.txt patch, which I will remove.

This one updates doc strings per Rich's suggestion.

Also, his mention of metadata and "as if by assoc" led me to beef up the new test cases to check that metadata is correct, and I thus found that my new array-map constructor was not doing the right thing. This one does.

There is still no implementation of Rich's #3 yet. Just wanted to get this one up there in case someone else builds on it before I do.

Comment by Andy Fingerhut [ 09/Sep/12 3:07 AM ]

Patch clj-1065-do-map-constant-duplicate-key-checks-compile-time-only-v1.txt only makes changes that should eliminate run-time checks for duplicate map keys, if they are compile-time constants.

It is currently separate from the changes to those for the set/map constructor functions, since I am less sure about these changes. I'm not terribly familiar with the compiler internals, and I might be going about this the wrong way. Better to get separate feedback on these changes alone. I'm happy to merge them all into one patch if both parts look good.





[CLJ-1064] Broken update-in for empty keys vector Created: 07/Sep/12  Updated: 08/Sep/12  Resolved: 08/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Gunnar Völkel Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None


 Description   

Using update-in with an empty keys vector produces unexpected results:
(update-in {:a 10 :b 20} [] dissoc :a)
⇒ {nil nil, :a 10, :b 20}
(update-in {:a 10 :b 20} [] assoc :c 99)
⇒ {nil {:c 99}, :a 10, :b 20}

The empty keys vector occurs in scenarios where you search on nested maps and later want to update the nested map structure at found paths.

A well-defined behavior is to check the case when the keys vector is empty and then apply only the given function on the given map: (apply f m args)



 Comments   
Comment by Nicola Mometto [ 07/Sep/12 6:37 AM ]

I think passing in an empty vector should rather be considered an error, since the doc specifies that `ks should be a sequence of keys`.

The same wrong (in my opinion) behaviour is shown by assoc-in

user=> (assoc-in {} [] 1)

Unknown macro: {nil 1}
Comment by Gunnar Völkel [ 07/Sep/12 7:47 AM ]

Specifying an empty vector is no error in case the vector is not manually specified but computed as in the scenario I mentioned above.
"(apply f m args)" in case of an empty vector is the natural continuation of the usual behavior of update-in:

  • update-in with 2 keys the second level map is updated
  • update-in with 1 key the first level map (child of given map) is updated
  • update-in with no key the given map (zero level) is updated.

Otherwise, you will always have to wrap update-in in something like the following when the keys vector is computed:

(if (seq keys) (update-in m keys f args) (apply f m args))

Comment by Andy Fingerhut [ 07/Sep/12 11:01 AM ]

I believe this is a duplicate of CLJ-373. Please add your comments and/or suggested patches to that ticket rather than this one. This one should likely be closed as a duplicate. Let me know if you can think of any reason why this one covers new ground that CLJ-373 does not.

Comment by Gunnar Völkel [ 08/Sep/12 6:02 AM ]

Yes, you are right - it is a duplicate.

Comment by Andy Fingerhut [ 08/Sep/12 10:15 AM ]

Closed, as it is a duplicate of CLJ-373.





[CLJ-1062] CLJ-940 breaks compilation of namespaces that don't have any public functions Created: 05/Sep/12  Updated: 01/Mar/13  Resolved: 21/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: Release 1.5

Type: Defect Priority: Critical
Reporter: Michael Klishin Assignee: Stuart Sierra
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File 0001-CLJ-1062-fix-require-1.patch    
Patch: Code
Approval: Ok

 Description   

CLJ-940 that was recently committed to master break compilation of namespaces that don't have any public functions in them
(for example, like https://github.com/michaelklishin/monger/blob/master/src/clojure/monger/json.clj that only extends
a protocol).

This affects several of clojurewerkz.org projects that no longer can compile with 1.5.0-master-SNAPSHOT.



 Comments   
Comment by Michael Klishin [ 05/Sep/12 8:39 PM ]

To be more correct: it breaks compilation of namespaces that require/load such ns without any public functions.

Comment by Michael Klishin [ 05/Sep/12 8:46 PM ]

An example project that reproduces the issue (see in the README):
https://github.com/michaelklishin/clj1062

Comment by Stuart Sierra [ 21/Sep/12 8:28 AM ]

Patch applied.





[CLJ-1061] when-first double evaluation Created: 04/Sep/12  Updated: 20/Oct/12  Resolved: 20/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Steve Miner Assignee: Stuart Sierra
Resolution: Completed Votes: 1
Labels: patch
Environment:

Mac OS X 10.8.1, Java 1.7.0_06


Attachments: Text File 0001-avoid-double-evaluation-in-when-first.patch    
Patch: Code
Approval: Ok
Waiting On: Rich Hickey

 Description   

The when-first macro will evaluate the xs expression twice. Admittedly, it does exactly what the doc string says, but that seems undesirable to me. Even without side effects, there's a potential performance issue if xs is some expensive operation.

Patch attached. The main diff is:

- `(when (seq ~xs)
- (let [~x (first ~xs)]
- ~@body))))
+ `(when-let xs# (seq ~xs)
+ (let ~x (first xs#)
+ ~@body))))



 Comments   
Comment by Stuart Sierra [ 21/Sep/12 7:39 AM ]

Screened.





[CLJ-1055] "be come" should be "become" Created: 01/Sep/12  Updated: 17/Sep/12  Resolved: 17/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Daniel Hofstetter Assignee: Unassigned
Resolution: Completed Votes: 1
Labels: None

Approval: Ok

 Description   

There is a typo in core.clj in the docs for "agent", "ref", and "atom": it should be "become" instead of "be come".



 Comments   
Comment by Stuart Halloway [ 17/Sep/12 7:11 AM ]

Thanks!





[CLJ-1054] Syntax quoted form produces a sequence, not a list Created: 31/Aug/12  Updated: 18/Sep/12  Resolved: 18/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Andrei Zhlobich Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

Syntax quote returns clojure.lang.Cons instead of IPersistenList.
But simple quote always returns list.

(list? '(1))     => true
(list? '(1 2 3)) => true
(list? `(1))     => true
(list? `(1 2 3)) => false


 Comments   
Comment by Stuart Halloway [ 18/Sep/12 6:42 AM ]

It is unusual in Clojure to expect/rely on concrete list? checks, particularly given the prevalence of seq?

If the behavior documented here is causing problems, please discuss use case on mailing list, and then we can open a ticket.





[CLJ-1052] assoc should throw exception if missing val for last key Created: 29/Aug/12  Updated: 20/Oct/12  Resolved: 20/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.2, Release 1.3, Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Andy Fingerhut Assignee: Unassigned
Resolution: Completed Votes: 8
Labels: None

Attachments: Text File clj-1052-assoc-should-throw-exc-if-missing-val-patch3.txt    
Patch: Code and Test
Approval: Ok

 Description   

https://groups.google.com/forum/?fromgroups=#!topic/clojure/k2R4OdPUCzg

Suggested by Ambrose Bonnaire-Sergeant:

I think assoc should throw an error when applied with uneven arguments.

Currently, the "missing" value is just replaced with nil.

(assoc {} :a 1 :b)
;=> {:a 1, :b nil}



 Comments   
Comment by Andy Fingerhut [ 29/Aug/12 4:42 PM ]

Patch clj-1052-assoc-should-throw-exc-if-missing-val-patch1.txt dated Aug 29 2012 makes assoc throw an IllegalArgumentException if more than one key is given, but the last key has no value. It includes a few simple test cases with correct and incorrect arguments to assoc.

Comment by Ambrose Bonnaire-Sergeant [ 29/Aug/12 5:14 PM ]

IMO if the error message included something like "assoc expects even number of arguments after target, found odd number", or some mention of the number of arguments the error would be clearer to me.

Comment by Andy Fingerhut [ 29/Aug/12 6:06 PM ]

clj-1052-assoc-should-throw-exc-if-missing-val-patch2.txt is identical to the now-removed -patch1.txt, except for the text of the exception thrown, updated as per Ambrose's suggestion.

Comment by Stuart Halloway [ 18/Sep/12 6:51 AM ]

The patch appears correct. It does introduce a single extra (next) per iteration into the success path, although that seems unlikely to dominate the work. Wouldn't hurt to add as assessment showing this is no slower for correct programs.

Comment by Andy Fingerhut [ 19/Sep/12 2:03 AM ]

Test platform: Mac OS X 10.6.8 + Oracle/Apple Java 1.6.0_35 Java HotSpot(TM) 64-Bit Server VM

With latest Clojure master as of Sep 19 2012:

Clojure 1.5.0-master-SNAPSHOT
user=> (set! unchecked-math true)
true
(defn count-maps [n]
(let [base {:a 1}]
(loop [i n
sum 0]
(if (zero? i)
sum
(let [m1 (assoc base :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9 :j 10)]
(recur (dec i) (+ sum (count m1))))))))
#'user/count-maps
user=> (time (count-maps 10000000))
"Elapsed time: 48784.077 msecs"
100000000
user=> (time (count-maps 10000000))
"Elapsed time: 49028.52 msecs"
100000000
user=> (time (count-maps 10000000))
"Elapsed time: 50314.729 msecs"
100000000

Same Clojure version, plus the patch that was screened:

user=> (time (count-maps 10000000))
"Elapsed time: 49576.191 msecs"
100000000
user=> (time (count-maps 10000000))
"Elapsed time: 49957.866 msecs"
100000000
user=> (time (count-maps 10000000))
"Elapsed time: 52149.998 msecs"
100000000

(average of 3 times after patch) / (average of 3 times before patch) = 1.0240

So 2.4% slowdown on average for that test case. I should add that I'm not a statistician, but note that this 2.4% difference is less than the variation in run time from one run to the next of the same experiment. Likely any real statistician would recommend collecting a lot more data before asserting there is a change in performance.

Comment by Andy Fingerhut [ 05/Oct/12 7:38 AM ]

clj-1052-assoc-should-throw-exc-if-missing-val-patch3.txt dated Oct 5 2012 is the same as the previous patch clj-1052-assoc-should-throw-exc-if-missing-val-patch2.txt dated Aug 29 2012 except some context lines have been updated so that it applies cleanly using git. The older version will be removed in a minute.





[CLJ-1051] Recursive function raises "call unbound fn" exception Created: 27/Aug/12  Updated: 01/Mar/13  Resolved: 09/Nov/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Armando Blancas Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None
Environment:

OSX


Attachments: File expr.clj    

 Description   

I've tried to reduce the code to the minimum that will reproduce the problem. This is a parser combinator library that uses the "list of successes" method. The test is a simple expression for adding one-digit integers with support for parens; sample input might be "1+(2+3)+4".

Having declared the parsers (see attached file), the expression parser is this:

(declare expr)

(def factor
  (choice (between (match \() (match \)) expr)
	  integer))

(def expr
  (bind factor
       (fn [t]
	 (choice (bind (match \+) (fn [_] (bind expr (fn [e] (result (+ t e))))))
	         (result t)))))

With the above, I get this error:

Clojure 1.4.0
user=> (load-file "expr.clj")
#'user/expr
user=> (run expr "(3)")      
IllegalStateException Attempting to call unbound fn: #'user/expr  clojure.lang.Var$Unbound.throwArity (Var.java:43)

I can, however, avoid this error if I code the (factor) function by expanding the code of the parser (between):

(declare expr)

(def factor*
  (choice (bind (match \() (fn [_]
          (bind expr       (fn [e]
	  (bind (match \)) (fn [_] (result e)))))))
	  integer))

(def expr
  (bind factor*
       (fn [t]
	 (choice (bind (match \+) (fn [_] (bind expr (fn [e] (result (+ t e))))))
	         (result t)))))

And now I can do:

Clojure 1.4.0
user=> (load-file "expr.clj")
#'user/expr
user=> (run expr "(3)")      
3
user=> (run expr "1+(2+3)+(4+5)")
15

The ability to reuse parser and add conveniences like (between) is key for this style of parsing.



 Comments   
Comment by Kevin Downey [ 27/Aug/12 6:03 PM ]

this is not a bug in clojure.

declare creates an unbound var then your def tries to use the value of the var before you have given it a value.

declare does not let you use a value of a var before you have given it one (via def or whatever).

Comment by Kevin Downey [ 27/Aug/12 6:05 PM ]

meta comment:
I would close this as "Declined", but I am not sure if that is kosher for me to do.

Comment by Armando Blancas [ 27/Aug/12 10:28 PM ]

Thanks for looking into this.

Just want to point out that as far as the declare and the use of expr as a forward reference, the second scenario I've presented (with factor*) uses (declare) the same way, yet it works: the var "expr" in (factor*) ends up pointing to the root value set later, but before it runs.

Seems to me similar to this case, where f is defined in terms of itself and it works fine, having the var "f" obtained its root binding after the def form runs:

user=> (def f (fn [n] (if (< n 1) 1 (* n (f (- n 1))))))
#'user/f
user=> (f 6)
720

Given that I've got a usage that works, I would suspect that there's something about the first case that prevents the root binding to be visible to the declared var.

Comment by Kevin Downey [ 28/Aug/12 3:25 AM ]

the formatting of the second case makes it hard to read, but it looks like expr is referenced inside a function, so the var #'expr will not be derefed until the function is run.

Comment by Armando Blancas [ 28/Aug/12 12:32 PM ]

Though the difference isn't quite apparent to me, I kind of grasp the idea that the var may be in one case deref'ed earlier in one case than the other because calls to (bind) are eager and in the case of the additional call to (between) the var is inside the function. I'll ask the board for advice on this and this ticket can be closed. Thanks.

Comment by Stuart Sierra [ 09/Nov/12 8:51 AM ]

Closed based on discussion in comments.





[CLJ-1050] Remove a lock in the common case of deref of delay Created: 26/Aug/12  Updated: 18/Sep/12  Resolved: 18/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Nicolas Oury Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: enhancement, patch, performance

Attachments: Text File 0001-No-lock-in-the-common-path-for-delays.patch    

 Description   

Currently, when deref is called in Delay.java, a lock on the Delay is always acquired.
This is wasteful as most of the time you just want to read the val.

The attached patch changes this behaviour to the following:

  • val is initialised to a known secret value. (During its constructor so it is visible from any thread).
  • When deref is called, val is checked to the known secret value.
  • If it is not the secret value, then it has to be the value computed by the function and we return it.
  • If it is the secret value, then we lock this object and revert to the current behaviour.

This is faster than what is done currently and can be very much faster if there is contention on the delay.



 Comments   
Comment by Nicolas Oury [ 27/Aug/12 2:37 AM ]

Please close and reject. The patch is not working if val has non final fields.





[CLJ-1048] add test.generative to Clojure's tests Created: 21/Aug/12  Updated: 01/Mar/13  Resolved: 07/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Enhancement Priority: Major
Reporter: Stuart Halloway Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File add-test-generative.patch    
Patch: Code and Test
Approval: Ok

 Description   

The 0.1.5 release of test generative includes data generators and specs based on data generation, plus a runner that can run both c.t and c.t.g. tests under the same umbrella.



 Comments   
Comment by Stuart Halloway [ 21/Aug/12 10:26 PM ]

Note that this patch also removes the cyclic load tests. Those tests relied on leaving broken code on the test classpath, which is very hostile to tooling (in this case the test runner's ability to walk the code in the test directory.)

I believe such tests are an antipattern, and should be implemented differently or e.g. placed in an ancillary test suite.

Comment by Fogus [ 22/Aug/12 10:32 AM ]

I agree with you position on the cyclic load tests. The patch looks sane to me and ran without hitch. A couple points of note:

  • This requires one to re-run antsetup – not a problem, but it might trip a few people
  • The final output of the test run is different than before. In the case of a successful run we now see only the generative success stats. Is the regular clojure.test stats included? It's not clear to me, but I don't think they are. In the fail case we see something like the following. I actually like the map output better, but one advantage to the stack trace output was that it sometimes helped identify code bugs. In any case, it would be nice to see an aggregate score at the end. This is a test.generative feature request I know.
     [java] {:clojure.test/vars (test-equality),
     [java]  :thread/name "main",
     [java]  :pid 8682,
     [java]  :thread 1,
     [java]  :type :assert/fail,
     [java]  :level :warn,
     [java]  :test/actual (not (not true)),
     [java]  :test/expected (not (= nil nil)),
     [java]  :line 28,
     [java]  :tstamp 1345649256308,
     [java]  :file "data_structures.clj"}

In all, I like this! Now we need to start thinking up more specs.

Comment by Stuart Halloway [ 22/Aug/12 11:51 AM ]

The stats reports are aggregate, i.e. they rollup both the generative and clojure.test stats. It would be straightforward to separate these in the report. I will look at doing that in the next drop of c.t.g.

The output already includes stack traces for errors, but not for test failures. I thought this was consistent with clojure.test, but maybe I missed something.

Comment by Fogus [ 22/Aug/12 12:59 PM ]

Thanks for the clarification Stu. You're right that the exception behavior is consistent, the confusion was my own.

Comment by Stuart Sierra [ 07/Sep/12 11:34 AM ]

Patches have been applied as of September 1, 2012.





[CLJ-1042] [PATCH] Allow negative substring indices for (subs) Created: 14/Aug/12  Updated: 19/Sep/12  Resolved: 17/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Ian Eure Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: enhancement, patch

Attachments: Text File clj-1042-negative-indices-patch3.txt     Text File negative-subs.patch    
Patch: Code and Test

 Description   

This adds Python-style negative string indices for (subs), e.g.:

(subs "foo bar" -3) ;; -> "bar"



 Comments   
Comment by Andy Fingerhut [ 16/Aug/12 7:17 PM ]

Ian, thanks for the patch. It is Rich Hickey's policy only to consider applying patches to Clojure from those who have signed a Clojure contributor agreement: http://clojure.org/contributing

Were you interested in doing so, or perhaps it is already in progress?

Comment by Ian Eure [ 20/Aug/12 11:44 AM ]

I wasn't aware that this was necessary. I'm mailing the form in.

Comment by Andy Fingerhut [ 27/Aug/12 7:56 PM ]

Patch clj-1042-negative-subs-patch2.txt dated Aug 27 2012 is identical to Ian Eure's negative-subs.patch, except it is in the desired git format.

Ian, for future reference on creating patches in the desired format, see the instructions under the heading "Development" on this page: http://dev.clojure.org/display/design/JIRA+workflow

Comment by Ian Eure [ 28/Aug/12 11:47 AM ]

Thanks, will do.

Comment by Steve Miner [ 04/Sep/12 3:53 PM ]

If Clojure decides to support Python-style negative indices, you should also consider adding support to subvec.

Comment by Ian Eure [ 06/Sep/12 12:17 PM ]

Patch extended to support negative indices on (subvec) as well.

Comment by Adrian Bendel [ 07/Sep/12 8:01 AM ]

The arg to rindex should probably be tagged with ^clojure.lang.Counted instead of ^String now.

Comment by Steve Miner [ 07/Sep/12 1:31 PM ]

Regarding the previous comment, String is a Java class so it isn't a clojure.lang.Counted. Is the type hint necessary? Maybe it should be on the call rather than the defn.

Ignoring the type hinting, I'll suggest a slightly simpler way to implement the rindex logic:

(defn rindex [coll i]
(if (neg? i) (+ (count coll) i) i))

In any case, I'm not sure rindex should be public even if you want the subs and subvec enhancements. Someone needs to make the case for adding a new function to core.

The Pythonic negative index is a debatable feature since it's pretty easy to implement for yourself if you want it.

Comment by Adrian Bendel [ 07/Sep/12 11:05 PM ]

Sorry, the type hint on rindex args isn't necessary at all. Just looked up in the source, calling count should never be reflective, since (count ..) emits calls to clojure.lang.RT/count.

Your solution looks good.

Comment by Stuart Halloway [ 17/Sep/12 7:07 AM ]

Negative indices were considered and rejected a long time ago. (I am merely conveying information--I have no strong opinion on this one.)

Comment by Andy Fingerhut [ 17/Sep/12 12:07 PM ]

Note: If some people really like negative index behavior as in Perl or Python, it is straightforward to create a library of functions in a different namespace, perhaps with different names, that can do it. Perhaps a "pythonisms" library?

Comment by Ian Eure [ 18/Sep/12 12:31 PM ]

Would this be accepted as part of clojure.string instead? I considered putting it there, but thought it would be confusing to have multiple substring functions in different namespaces.

This is very helpful in practice, and I'd really like to see at least the (subs) stuff in Clojure.

Comment by Andy Fingerhut [ 18/Sep/12 2:52 PM ]

Disclaimer: I'm no Clojure/core member, so can't speak authoritatively on whether something would or would not be accepted into clojure.string.

However, given that clojure.string is distributed with clojure.core, my guess is it would not be accepted. You'd be able to get things like this out for you and others as a separate library distributed on Clojars. That would also make it easy to include other Python-like things that you don't find in Clojure already.

Comment by Ian Eure [ 18/Sep/12 4:02 PM ]

This isn't about "python-like things," this is about a useful feature. Lots of languages support this: Perl, PHP, Ruby, Python, JavaScript, to name a few. Are you really suggesting that I should create a whole package for a version of a function in clojure.core with slightly different semantics? That's insane.

Anyway, I'm done wasting my time trying to navigate this hopelessly broken process. Maybe it would have been accepted if I included yet another way to interoperate with Java types.

Comment by Michael Klishin [ 18/Sep/12 5:09 PM ]

Stuart, do you remember why specifically negative indexes were rejected? Developing a separate library for a minor improvement to an existing function sounds unreasonable.

Comment by Carlos [ 18/Sep/12 5:10 PM ]

some explanation about this topic was given by Rich Hickey himself here: http://news.ycombinator.com/item?id=2053908

citation:
"...Yes, there is a backlog from when it was just me, and it will take a while to whittle down. We have finite resources and have to prioritize. I can assure you we have more important things to concentrate on than your negative index substring enhancement, and are doing so. You'll just have to be patient. Or, if you insist, I'll just reject it now because a) IMO it's goofy, b) you can make your own function that works that way c) we don't get a free ride from j.l.String, d) it begs the question of negative indices elsewhere..."

i've been following this thread hoping this feature would be included. but whatever the reason was for the rejection, i'm sure it was thoughtful. great thanks for this wonderful language, and thanks Ian Eure for his effort.

Comment by Steve Miner [ 18/Sep/12 5:25 PM ]

That HN link eventually leads back to CLJ-688 which was rejected.

Comment by Stuart Halloway [ 19/Sep/12 12:03 PM ]

Michael: A proposal for negative indexes would need to be systematic in considering implications for all functions that have index arguments.

Ian: Clojure is driven by design, not incremental piling of features.

All: clojure.string is incomplete in more important and fundamental ways than negative indexes. This sucks now, and will suck worse as more code is written in different dialects. I find myself wishing string was a contrib, so we could iterate faster.

Comment by Andy Fingerhut [ 19/Sep/12 1:34 PM ]

Stuart: Any specific proposals for how you'd like to see clojure.string improve? If it can be made a contrib, that would be cool, but understood if that would be considered too breaking of a change. Even if it isn't made a contrib, having tickets for improvement ideas you are willing to see means patches might get written, and they'll get in some time.





[CLJ-1041] reduce-kv on sorted maps should stop on seeing a Reduced value Created: 10/Aug/12  Updated: 18/Aug/12  Resolved: 18/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Alan Malloy Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File sorted-map-kvreduce.patch    
Patch: Code and Test
Approval: Ok

 Description   

The current implementation is dereferencing Reduced and returning them up the chain; but that means that parent nodes don't know the reduction has completed, so the reduction might continue along other paths down the tree.

This patch touches the same areas of code as CLJ-1040 so will have conflicts if both patches are merged separately. However, as noted in my comment on CLJ-1040, I don't think the patch there is correct yet, so I've also included a commit (7beb14256) to fix the issue in CLJ-1040. Thus, this patch can be merged independently of 1040's patch, solving both issues without a merge conflict.

This patch also includes tests for both issues, which fail before my commits are applied, and pass afterwards.



 Comments   
Comment by Aaron Bedra [ 14/Aug/12 7:46 PM ]

Patch applies cleanly against 4004d267e124f12b65b0d7fb6522f32a75e3c4fb. Submitter confirmed on the CA list.





[CLJ-1040] reduce-kv on sorted maps should reduce, in sorted order Created: 10/Aug/12  Updated: 01/Mar/13  Resolved: 15/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Stuart Halloway Assignee: Stuart Halloway
Resolution: Duplicate Votes: 0
Labels: None

Attachments: Text File fix-reduce-kv-for-sorted-maps.patch    
Approval: Ok

 Description   

Currently reduces, but not in sorted order.



 Comments   
Comment by Alan Malloy [ 10/Aug/12 3:09 PM ]

Stuart, your patch doesn't check for Reduced after calling f on the current node; I think you need to move that check along with the call to f.

Comment by Alan Malloy [ 10/Aug/12 3:18 PM ]

CLJ-1041 is a related issue, and its patch also includes a commit that I think would fix your patch.





[CLJ-1038] Docstring for deliver doesn't match behavior Created: 07/Aug/12  Updated: 01/Mar/13  Resolved: 24/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Colin Jones Assignee: Colin Jones
Resolution: Completed Votes: 0
Labels: documentation

Attachments: Text File 0001-Update-docstring-for-deliver-s-actual-behavior.patch     Text File correct-deliver-docstring.patch    
Patch: Code
Approval: Ok

 Description   

The docstring for deliver doesn't match the actual behavior. It says an exception gets thrown on multiple delivers, but that's no longer the case, as of 1.3 (hat tip to clgv on irc).

user=> (doc deliver)
-------------------------
clojure.core/deliver
([promise val])
  Alpha - subject to change.
  Delivers the supplied value to the promise, releasing any pending
  derefs. A subsequent call to deliver on a promise will throw an exception.
nil
(let [p (promise)] 
  (deliver p "hi") 
  (deliver p "bye") 
  @p)
;=> "hi"

This patch updates the docstring to reflect actual behavior: "will throw an exception." -> "will have no effect."



 Comments   
Comment by Stuart Halloway [ 10/Aug/12 1:48 PM ]

Both patches are correct. Colin's patch documents the side effect, my variant also commits to the return values. Take your pick.

Comment by Rich Hickey [ 10/Aug/12 3:09 PM ]

Don't doc return

Comment by Stuart Sierra [ 24/Aug/12 7:41 AM ]

CLJ-1038 Update docstring for deliver's actual behavior (patch applied Aug 15, 2012)





[CLJ-1035] Remove the need to use ":import" of a record Created: 29/Jul/12  Updated: 10/Aug/12  Resolved: 10/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Warren Lynn Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

Right now if I need to use a record defined in another name space, I need to do this:

(ns myproj.test.xyz
(:use [myproj.xyz])
(:import [myproj.xyz MyRecord])

Hope we can remove the need of ":import" clause.



 Comments   
Comment by Stuart Halloway [ 10/Aug/12 12:44 PM ]

Hi Warren,

Importing a Java class and using a record are two logically distinct ideas, hence two separate steps in your code. Note that using a namespace makes the defrecord constructor fns (e.g. >MyRecord and map>MyRecord) available without a second step.

Please discuss ideas on the mailing list before using JIRA to make suggestions.

Cheers

Comment by Warren Lynn [ 10/Aug/12 2:19 PM ]

Thanks for giving it a thought.

I think it is conceptually simple/consistent to say "if you use a namespace, then all the public symbols in that namespace is available without namespace qualification". It is unnecessary to remind people "Hey, record is an actually a Java class so the rules do not apply". I think it is the right choice for Clojure to integrate closely with the host language, but it is not the objective to expose the host details when not needed. If you say "this is a compromise due to some implementation consideration", then I can understand. But I disagree with the rationale you mentioned.





[CLJ-1034] "Conflicting data-reader mapping" triggered when the same data_readers.clj is on the classpath twice Created: 26/Jul/12  Updated: 01/Sep/12  Resolved: 01/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Phil Hagelberg Assignee: Unassigned
Resolution: Completed Votes: 10
Labels: None

Attachments: File clj_1034_data_readers_fix.diff    
Approval: Ok

 Description   

If you have two data_readers.clj files on the classpath that agree with one another about the mapping of a given literal, Clojure still claims there is a conflict.



 Comments   
Comment by Justin Kramer [ 13/Aug/12 9:59 AM ]

This comes up when using checkout dependencies in Leiningen. If the checked-out project contains data_readers.clj, Clojure will throw an exception.

To reproduce:

user=> (spit "/tmp/data_readers.clj" "{foo/bar foo.core/bar}")
nil
user=> (with-redefs [clojure.core/data-reader-urls (constantly [(java.net.URL. "file:/tmp/data_readers.clj")])] (#'clojure.core/load-data-readers))
{foo/bar #'foo.core/bar}
user=> (with-redefs [clojure.core/data-reader-urls (constantly [(java.net.URL. "file:/tmp/data_readers.clj")])] (#'clojure.core/load-data-readers))
ExceptionInfo Conflicting data-reader mapping clojure.core/ex-info (core.clj:4227)

Comment by Justin Kramer [ 13/Aug/12 10:21 AM ]

Attached clj_1034_data_readers_fix.diff with simple fix: checks that new mappings actually point to different vars before claiming a conflict.





[CLJ-1032] seque leaks threads from the send-off pool Created: 25/Jul/12  Updated: 01/Mar/13  Resolved: 19/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Alan Malloy Assignee: Unassigned
Resolution: Completed Votes: 5
Labels: None

Attachments: Text File seque.patch    
Patch: Code and Test
Approval: Ok

 Description   

Because a new (fill) action is created every time an item is (drain)ed, the LBQ gets loaded up with piles of EOS markers. If the output seq is consumed faster than the input sequence can produce items, then the original agent action does all of the filling in a single action, while the agent's queue continues to back up with (fill) actions. Eventually the entire sequence is consumed, and each queued action does a blocking .put of an EOS marker; once the queue has filled up, one of these actions blocks forever, since nobody will ever .take from the queue again.

The attached patch does two things:

  • Make sure to put exactly one EOS marker in the stream, by setting the agent's state to nil if and only if a .offer of EOS has been accepted.
  • Replace all occurrences of .put with .offer (and appropriate checking of the return value). This is necessary because if .put ever blocks, it's possible for the system to remain in that state forever (say, because the client stops consuming the queue), thus leading to the same leaked-thread scenario.

The diff is a little bit inconvenient to read because of indentation changes; https://gist.github.com/b7ecd4395a0d3d473de6 is an ignore-whitespace view of the patch for convenience.



 Comments   
Comment by Andy Fingerhut [ 26/Jul/12 3:50 AM ]

Sorry for me just triggering on the function "seque" without a deep understanding, but is this by any chance the same issue as described in CLJ-823? If so, since this one has a patch and that one doesn't, might be nice to mark CLJ-823 as a duplicate of this one.

Comment by Alan Malloy [ 26/Jul/12 4:48 AM ]

No, these are separate issues. CLJ-823 is just a special case of the general problem that seque is not usable from within an agent action. I have an implementation of seque using futures instead of agents so that this isn't a problem, but that has other problems of its own, specifically if you don't fully consume the seque you wind up leaking a future object.

Comment by Alan Malloy [ 19/Aug/12 8:11 PM ]

Marking as resolved since the patch has been applied in master.





[CLJ-1031] Website documentation for evaluation has misleading information about "load" Created: 25/Jul/12  Updated: 10/Aug/12  Resolved: 10/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Ola Bini Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None


 Description   

In the documentation at http://clojure.org/evaluation the documentation says "(load reader)" and the verbiage below mentions loading from a stream or file. This is misleading since "load" doesn't take a reader, but a resource. It would also be great to have pointers to load-reader and load-string here. (Where is the source for the website generated from? Is it possible to create a patch/pull request for it?)



 Comments   
Comment by Stuart Halloway [ 10/Aug/12 1:08 PM ]

Ola:

Thanks for the report. The website is wikispaces, no easy patch approach AFAIK.





[CLJ-1028] (compile) crashes with NullPointerException if public function 'load' is defined Created: 20/Jul/12  Updated: 20/Jul/12  Resolved: 20/Jul/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Ben Kelly Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: Compiler, bug
Environment:

Linux, OpenJDK 1.6.0 64bit


Attachments: File stack-trace    

 Description   

When performing AOT compilation, if the namespace being compiled or one of the namespaces :required by it defines a public function named 'load', the compiler will crash with a NullPointerException.

The following code demonstrates this:

(ns ca.ancilla.kessler.core (:gen-class)) (defn load [x] x) (defn -main [& args] 0)

When run directly, with 'clojure -m ca.ancilla.kessler.core' or 'clojure ca/ancilla/kessler/core.clj', it runs as expected. When loaded with 'clojure -i' and (compile)d, however, or when automatically compiled by 'lein run', it results in a NullPointerException (the complete stack trace is attached).

This occurs whether or not 'load' or actually called. It does not, however, occur if 'load' is private.



 Comments   
Comment by Ben Kelly [ 20/Jul/12 12:43 PM ]

If you add (:refer-clojure :exclude [load]) to the (ns), it works fine:

(ns ca.ancilla.kessler.core (:refer-clojure :exclude [load]) (:gen-class))
(defn load [x] x)
(defn -main [& args] 0)

Thanks to llasram on IRC for discovering this.

Comment by Stuart Halloway [ 20/Jul/12 4:35 PM ]

You should not replace functions in clojure.core. This is left legal (with a loud CONSOLE warning) for compatibility, but programs that do it are in error.

Comment by Ben Kelly [ 20/Jul/12 10:06 PM ]

So, just to make sure that I have this right, then...

If I want to create a namespace with a public function that shares a name with a function in clojure.core, the only supported way of doing this is to (:refer-clojure :exclude [list of all such functions])?

If so, it would be nice if the warning were replaced with an error, rather than having the compiler emit an error and then crash.





[CLJ-1025] Enable support for \x.. escaped characters. Created: 13/Jul/12  Updated: 19/Oct/12  Resolved: 19/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Dave Sann Assignee: Unassigned
Resolution: Declined Votes: 1
Labels: None
Environment:

All


Attachments: Text File 0001-adding-support-for-x-escape-characters.patch    
Patch: Code and Test
Approval: Not Approved

 Description   

see: https://groups.google.com/d/topic/clojure/Kl3WVtEE3FY/discussion

\x.. characters (which are the same as \u00.. characters) are produced by some systems. in particular clojurescript

Inability to read these characters hinders data interchange

After a quick look, I believe this capability can be easily introduced by adding a case to this
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L445 function.
Mirroring 'u' case and reading only 2 chars.



 Comments   
Comment by Andy Fingerhut [ 19/Jul/12 11:46 AM ]

Thanks for the patch, Dave. It is Rich Hickey's policy only to include code in Clojure written by those who have signed a Contributor Agreement (CA). See here for more details: http://clojure.org/contributing Have you signed one, or were considering it?

Comment by Andy Fingerhut [ 19/Jul/12 3:57 PM ]

Can someone find some documentation or spec somewhere that defines this \x.. format?

It is definitely different than the \x{...} syntax that exists in Perl, which permits one to insert an arbitrary Unicode character code point into a string (note: even supplementary ones that don't fit into a single UTF-16 code unit, as Java's and Clojure's \u.... is restricted to). http://perldoc.perl.org/perlunicode.html#Effects-of-Character-Semantics

Comment by Dave Sann [ 22/Jul/12 2:19 AM ]

http://es5.github.com/x7.html#x7.8.4

Comment by Dave Sann [ 31/Jul/12 4:35 AM ]

I am happy to sign the CA in principle. Just need to read and understand any implications for me.

Comment by Dave Sann [ 27/Aug/12 3:31 AM ]

CA will be with you shortly.

Comment by Dave Sann [ 16/Oct/12 3:11 AM ]

Can this go into 1.5?

Comment by Chas Emerick [ 19/Oct/12 8:10 AM ]

I'm hitting this now as well. But, adding support for JavaScript's flavour of \x.. escapes to the Clojure reader makes no sense to me. If escapes are to be used, then the \u.... format seems preferable (it supersets \x..).

However, all of the readers in play (Clojure reader, ClojureScript reader, edn) all play nice with Unicode, so there's no reason to be escaping anything except for \t, \n, and so on.

It looks like tweaking cljs' string implementations of IPrintWithWriter and IPrintable so that only those characters are escaped would be fairly easy. Right now, they're using goog.string.escape, which "encloses a string in double quotes and escapes characters so that the string is a valid JS string"; whatever escaping is appropriate for a "valid JavaScript string" seems irrelevant to what e.g. pr-str should produce.

I propose closing this ticket and moving the party to CLJS.

Comment by Stuart Halloway [ 19/Oct/12 1:55 PM ]

Following Chas's lead and closing this one. \x doesn't appear in the JSON spec, and a quick search of StackOverflow shows people stumbling over it from a bunch of other language platforms. I think we should root it out of ClojureScript.

Comment by Chas Emerick [ 19/Oct/12 1:58 PM ]

Great, I'll open a CLJS ticket with a patch tonight or tomorrow.

Comment by Ivan Kozik [ 19/Oct/12 2:39 PM ]

Re: "no reason to be escaping anything except for \t, \n": sometimes it is difficult or impossible to transmit all of Unicode (e.g. sending non-Character codepoints through XDomainRequest, or sending U+0000/U+FFFE/U+FFFF through many XHR implementations), so it might be nice to have an ASCII-only printing mode. Probably for another ticket, though.

Comment by Chas Emerick [ 19/Oct/12 7:59 PM ]

Here's the new ticket: http://dev.clojure.org/jira/browse/CLJS-400

@Ivan: I agree that options in this area would be good. There are a lot of edge cases where the defaults aren't right (e.g. I think escaping all nonprintables is a no-brainer for readably-printed strings).

I suspect planning out such details should probably happen [here](http://dev.clojure.org/pages/viewpage.action?pageId=4063586) or [here](https://github.com/edn-format/edn/issues).





[CLJ-1024] Varargs protococol impls can be defined but not called Created: 10/Jul/12  Updated: 14/Feb/13  Resolved: 13/Feb/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: Release 1.5

Type: Enhancement Priority: Minor
Reporter: Víctor M. Valenzuela Assignee: Stuart Halloway
Resolution: Declined Votes: 1
Labels: patch

Attachments: Text File 0001-CLJ-1024-Check-for-invalid-varags-destrucuring-uses.patch    
Patch: Code
Approval: Not Approved

 Description   

The compiler accepts this:

(deftype foo []
clojure.lang.IFn
(invoke [this & xs]))

However calling ((foo.) :bar) will throw an AbstractMethodError. Wouldn't some checking be desirable?



 Comments   
Comment by Tassilo Horn [ 11/Jul/12 1:20 AM ]

First of all, clojure.lang.IFn is no protocol but an interface. And it does not declare a

  public Object invoke(Object... obs)

method. It has an `invoke` method with 20 Object parameters followed by an Object... parameter, but to give an implementation for that, you have to specify every parameter separately, and the last Object... arg is just a normal argument that must be an Object[]. That's because Java-varags Type... parameters are just Java syntax sugar, but in the byte-code its simply a Type-array.

What your example does is provide an `invoke` implementation for the 2-args version, where the first parameter happens to be named `&`, which has no special meaning here. Take that example:

(deftype MyFoo []
  clojure.lang.IFn
  (invoke [this & xs]
    [& xs]))

((MyFoo.) 1 2)
=> [1 2]

But you are right in that `deftype`, `defrecord`, `defprotocol`, and `definferface` probably should error if user's seem to try to use varargs or destructuring.

Comment by Víctor M. Valenzuela [ 11/Jul/12 1:55 AM ]

Cheers for a most clarifying response.

The fact that the meaning of & gets 'subverted' makes the issue only (slightly) worse, in my opinion.

Just for the record, destructuring seems to work, at least for interface impls.

Comment by Tassilo Horn [ 11/Jul/12 2:42 AM ]

> The fact that the meaning of & gets 'subverted' makes the issue only (slightly) worse, in my opinion.

I agree. I'll attach a patch which checks for those invalid usages soon.

> Just for the record, destructuring seems to work, at least for interface impls.

Could you please provide a complete example demonstrating your statement?

I'm rather sure that varargs and destructuring don't work for any of defprotocol, definterface, deftype, defrecord, and reify. But you can use varargs and destructuring when providing dynamic implementations via `extend` (or `extend-protocol`, `extend-type`), because those impls are real functions in contrast to methods.

Comment by Tassilo Horn [ 11/Jul/12 2:43 AM ]

I attached a patch. Here's the commit message:

Check for invalid varags/destrucuring uses.

Protocol, interface method declarations and implementations don't allow for
varags and destructuring support. Currently, for example

(defprotocol FooBar
(foo [this & more]))

compiles just fine, and & is interpreted as a usual argument that happens to be
named & without special meaning. But clearly, the user wanted to specify a
varags parameter here. The same applies to definterface.

Similarly, providing method implementations via defrecord, deftype, and reify
don't allow for destructuring and varags (but dynamic extenions via extend do).

So this patch makes defprotocol, definterface, defrecord, deftype, and reify
throw an IllegalArgumentException if any argument vector contains a
destructuring form or varargs argument.

Comment by Víctor M. Valenzuela [ 12/Jul/12 3:13 AM ]

Glad you've considered my request.

As for destructuring, I was speaking after this example, which may or may not work like it looks like - I don't know.

(deftype foo []
clojure.lang.IFn
(invoke [this [a b] c] (println a b c)))

((foo.) [1 2] 3)

Comment by Tassilo Horn [ 12/Jul/12 8:22 AM ]

Indeed, descructuring seems to work for method implementations. I'll adapt my patch...

Comment by Tassilo Horn [ 12/Jul/12 8:42 AM ]

Revamped patch. Here's the commit message:

Protocol, interface method declarations don't allow for varags and
destructuring support. Currently, for example

  (defprotocol FooBar
    (foo [this & more]))

compiles just fine, and & is interpreted as a usual argument that happens to be
named & without special meaning. But clearly, the user wanted to specify a
varags parameter here. The same applies to definterface.

Similarly, providing method implementations via defrecord, deftype, and reify
don't allow for varags (but dynamic extenions via extend do).

So this patch makes defprotocol and definterface throw an
IllegalArgumentException if a user tries to use varargs and destructuring in
method signatures.

Similarly, defrecord, deftype, and reify throw an IllegalArgumentException if
any method implementation arglist contains a varargs argument.

Comment by Andy Fingerhut [ 12/Jul/12 3:43 PM ]

Tassilo, with your patch 0001-CLJ-1024-Check-for-invalid-varags-destrucuring-uses.patch dated July 12, 2012, I get the following error message while testing, apparently because some metadata is missing on the new functions your patch adds to core:

[java] Testing clojure.test-clojure.metadata
[java]
[java] FAIL in (public-vars-with-docstrings-have-added) (metadata.clj:45)
[java] expected: (= [] (remove (comp :added meta) public-vars-with-docstrin
gs-not-generated))
[java] actual: (not (= [] (#'clojure.core/throw-on-varargs-and-destr #'cl
ojure.core/throw-on-varargs)))

Comment by Tassilo Horn [ 13/Jul/12 2:10 AM ]

Hi Andy, this updated patch declares the two new checking fns private which makes the tests pass again.

Stupid mistake by me: Of course, I've tested the last version, too, but afterwards I decided it wouldn't be bad to add some docstrings, and of course, adding docstrings cannot break anything.

Comment by Aaron Bedra [ 14/Aug/12 7:58 PM ]

Patch applies cleanly against 4004d267e124f12b65b0d7fb6522f32a75e3c4fb. Submitter confirmed as a CA signer.

Comment by Aaron Bedra [ 14/Aug/12 8:02 PM ]

This looks ok to me, but it seems like a fair amount of duplication to accomplish the task. It seems like we should just be able to ask if it is ok to proceed, instead of having to pick which function needs to be called in what case.

Comment by Tassilo Horn [ 15/Aug/12 1:23 AM ]

Aaron, can you please elaborate? I don't get what you mean with duplication and asking if it is ok to proceed.

Comment by Tassilo Horn [ 31/Aug/12 1:40 AM ]

Rebased to apply cleanly on master again.

Comment by Víctor M. Valenzuela [ 31/Aug/12 7:11 AM ]

Pardon the silly contribution, but the added methods' usage of double-negations (when-not ...) seems unnecessary.

Comment by Tassilo Horn [ 31/Aug/12 8:03 AM ]

Hi Victor, this revamped patch removes the double-negation and is more concise and clearer as a result. So your comment wasn't as silly as you thought.

Comment by Tassilo Horn [ 14/Feb/13 1:36 AM ]

Hey Stu, do you mind to explain why you've declined the patch?

Comment by Marek Srank [ 14/Feb/13 8:52 AM ]

@Tassilo: https://groups.google.com/forum/#!topic/clojure-dev/qjkW-cv8nog

Comment by Tassilo Horn [ 14/Feb/13 10:03 AM ]

@Marek, Stu: Thanks, I've left a reply there: https://groups.google.com/d/msg/clojure-dev/qjkW-cv8nog/rMNFqbjNj-EJ





[CLJ-1023] non-tail-position try block breaks mutable fields in deftype Created: 08/Jul/12  Updated: 03/Dec/12  Resolved: 03/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Stuart Sierra Assignee: Rich Hickey
Resolution: Declined Votes: 0
Labels: None

Attachments: File demonstration.clj    

 Description   

The :unsynchronized-mutable fields of a deftype cannot be set! inside a try block that is not in tail position of the method.

See file *demonstration.clj* for an complete code example.



 Comments   
Comment by Rich Hickey [ 05/Sep/12 7:07 AM ]

I looked at this. The problem is that non-tail try blocks turn into closures, and thus the field gets propagated as a constant. IOW this can't work:

(deftype Foo4 [^:unsynchronized-mutable x]
  MutableX
  (set-x [this v]
    ((fn [] (set! x v)))
    v))

I'm not going to re-evaluate the try/closure approach right now, so I recommend you make a helper method that just does the assignment and then call that in the bigger context, as a workaround.

Comment by Timothy Baldridge [ 03/Dec/12 10:55 AM ]

Closing this as it requires more than a simple bug fix. If you feel that Rich's work-around is unsatisfactory please create a clojure-dev discussion about rewriting try-catch.





[CLJ-1019] ns-resolve doc has a typo Created: 30/Jun/12  Updated: 18/Aug/12  Resolved: 18/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: Release 1.5

Type: Defect Priority: Trivial
Reporter: Gabriel Horner Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: documentation

Attachments: Text File clj-1019-ns-resolve-doc-string-misspelling-patch1.txt     Text File fix_ns-resolve.patch    
Patch: Code
Approval: Ok

 Description   

The doc string for ns-resolve has a typo: environement should be environment.



 Comments   
Comment by Andy Fingerhut [ 12/Jul/12 12:54 PM ]

clj-1019-ns-resolve-doc-string-misspelling-patch1.txt dated July 12, 2012 is identical to fix_ns-resolve.patch of June 30, 2012, except it is in git format. It includes Gabriel's name and email address for proper attribution.

Comment by Aaron Bedra [ 14/Aug/12 8:07 PM ]

Patch applies cleanly against 4004d267e124f12b65b0d7fb6522f32a75e3c4fb. Submitter is a confirmed CA signer.





[CLJ-1014] Latest Clojure master doesn't build Created: 14/Jun/12  Updated: 20/Jul/12  Resolved: 20/Jul/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Edward Z. Yang Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None
Environment:

Ubuntu 10.10 Maverick
Java 1.6.0_20m OpenJDK (IcedTea6 1.9.13)



 Description   

Compile fails with the following error:

compile-clojure:
[java] Compiling clojure.core to /home/ezyang/Dev/clojure/target/classes
[java] Compiling clojure.core.protocols to /home/ezyang/Dev/clojure/target/classes
[java] Compiling clojure.core.reducers to /home/ezyang/Dev/clojure/target/classes
[java] Exception in thread "main" java.lang.ClassNotFoundException: jsr166y.ForkJoinPool, compiling:(clojure/core/reducers.clj:56)
[java] at clojure.lang.Compiler.analyzeSeq(Compiler.java:6462)
[java] at clojure.lang.Compiler.analyze(Compiler.java:6262)
[java] at clojure.lang.Compiler.analyzeSeq(Compiler.java:6443)
[java] at clojure.lang.Compiler.analyze(Compiler.java:6262)
[java] at clojure.lang.Compiler.analyze(Compiler.java:6223)
[java] at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5618)
[java] at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5054)
[java] at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3674)
[java] at clojure.lang.Compiler.analyzeSeq(Compiler.java:6453)
[java] at clojure.lang.Compiler.analyze(Compiler.java:6262)
[java] at clojure.lang.Compiler.analyze(Compiler.java:6223)
[java] at clojure.lang.Compiler$NewExpr$Parser.parse(Compiler.java:2478)
[java] at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
[java] at clojure.lang.Compiler.analyze(Compiler.java:6262)
[java] at clojure.lang.Compiler.analyzeSeq(Compiler.java:6443)
[java] at clojure.lang.Compiler.analyze(Compiler.java:6262)
[java] at clojure.lang.Compiler.access$100(Compiler.java:37)
[java] at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:518)
[java] at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
[java] at clojure.lang.Compiler.analyze(Compiler.java:6262)
[java] at clojure.lang.Compiler.analyze(Compiler.java:6223)
[java] at clojure.lang.Compiler.compile1(Compiler.java:7030)
[java] at clojure.lang.Compiler.compile1(Compiler.java:7025)
[java] at clojure.lang.Compiler.compile1(Compiler.java:7025)
[java] at clojure.lang.Compiler.compile(Compiler.java:7097)
[java] at clojure.lang.RT.compile(RT.java:387)
[java] at clojure.lang.RT.load(RT.java:427)
[java] at clojure.lang.RT.load(RT.java:400)
[java] at clojure.core$load$fn__4919.invoke(core.clj:5424)
[java] at clojure.core$load.doInvoke(core.clj:5423)
[java] at clojure.lang.RestFn.invoke(RestFn.java:408)
[java] at clojure.core$load_one.invoke(core.clj:5236)
[java] at clojure.core$compile$fn__4924.invoke(core.clj:5435)
[java] at clojure.core$compile.invoke(core.clj:5434)
[java] at clojure.lang.Var.invoke(Var.java:415)
[java] at clojure.lang.Compile.main(Compile.java:81)
[java] Caused by: java.lang.ClassNotFoundException: jsr166y.ForkJoinPool
[java] at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
[java] at java.security.AccessController.doPrivileged(Native Method)
[java] at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
[java] at clojure.lang.DynamicClassLoader.findClass(DynamicClassLoader.java:61)
[java] at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
[java] at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
[java] at java.lang.Class.forName0(Native Method)
[java] at java.lang.Class.forName(Class.java:264)
[java] at clojure.lang.RT.classForName(RT.java:2043)
[java] at clojure.lang.Compiler$HostExpr.maybeClass(Compiler.java:957)
[java] at clojure.lang.Compiler$HostExpr.access$400(Compiler.java:736)
[java] at clojure.lang.Compiler$NewExpr$Parser.parse(Compiler.java:2473)
[java] at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
[java] ... 35 more



 Comments   
Comment by Andy Fingerhut [ 14/Jun/12 11:42 AM ]

What command did you use?

From the error message, my guess is that you ran "ant" without first running "./antsetup.sh". If that is the case, run "./antsetup.sh" first. This is a new step added to readme.txt on May 7, 2012, because of the jsr166y.ForkJoinPool class used within Clojure to implement the new parallel reducers feature.

Comment by Edward Z. Yang [ 14/Jun/12 2:16 PM ]

Yep, that's exactly it. Can we setup ant to warn people if antsetup.sh hasn't been run?

Comment by Andy Fingerhut [ 14/Jun/12 5:12 PM ]

I don't know. I suspect if it could be done and it were a straightforward modification, a patch for that would be accepted. I suspect those who created antsetup.sh would have simply modified the build.xml file for ant, and not created antsetup.sh at all, if it were easy to do so.

Comment by Roy Truelove [ 26/Jun/12 3:58 PM ]

It can be done with just the build.xml but requires the Maven Ant Tasks jar to be in the local ant's classpath, which is not ideal.

Because a local maven install is anyway required by antsetup.sh, IMHO it would be best to remove the ant build all together and stick with solely with a maven build, no?

Comment by Andy Fingerhut [ 27/Jun/12 1:16 PM ]

I can't find the email right now, but I believe in the past Rich Hickey has expressed a preference for continuing to have a way to build Clojure using ant.

Comment by Stuart Halloway [ 20/Jul/12 4:49 PM ]

Ant is there for the convenience of various dinosaurs, myself included. In general you should use the maven build, as that is what the CI and release process do.





[CLJ-1012] partial function should also accept 1 arg (just f) Created: 12/Jun/12  Updated: 18/Aug/12  Resolved: 18/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4, Release 1.5
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Joel Martin Assignee: Unassigned
Resolution: Completed Votes: 1
Labels: None

Attachments: Text File 0001-Extend-partial-function-to-also-handle-one-argument-.patch     File CLJ-1012-partial-1-arity-test.diff    
Patch: Code and Test
Approval: Ok

 Description   

The partial function should accept just a function. This allows it to be properly used with apply.

E.g. This breaks (but shouldn't) if args are nil: (apply partial f args)



 Comments   
Comment by Michel Alexandre Salim [ 13/Jun/12 5:18 AM ]

Attached patch makes partial just returns f if called with only one argument. Not sure if this will have a performance impact or not; a Clojure/core member would probably be able to better judge if the use cases outweigh any performance hit.

Comment by Fogus [ 15/Aug/12 10:45 AM ]

Attached a patch adding a test for this ticket.

Comment by Fogus [ 15/Aug/12 10:47 AM ]

Original patch is trivial, but did not have a test. I added a test as a separate patch file.





[CLJ-1011] clojure.data/diff should cope with null and false values in maps Created: 12/Jun/12  Updated: 18/Aug/12  Resolved: 18/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Philip Aston Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: enhancement, patch

Attachments: Text File 0001-clojure.data-diff-cope-with-falsey-values-in-maps.patch    
Patch: Code and Test
Approval: Ok

 Description   

Current behaviour of clojure.data/diff:

=> (diff {:a false} {:a true})
(nil {:a true} nil)
=> (diff {:a false} {:a nil})
(nil nil nil)

Proposed behaviour:

=> (diff {:a false} {:a true})
({:a false} {:a true} nil)
=> (diff {:a false} {:a nil})
({:a false} {:a nil} nil)


 Comments   
Comment by Philip Aston [ 12/Jun/12 5:04 AM ]
 
From e03a8060214d122ea2ebadf9e8a368f7f593d9f4 Mon Sep 17 00:00:00 2001
From: Philip Aston <philipa@mail.com>
Date: Sun, 10 Jun 2012 13:11:36 +0100
Subject: [PATCH] clojure.data/diff: cope with falsey values in maps

---
 src/clj/clojure/data.clj           |   18 +++++++++++++++++-
 test/clojure/test_clojure/data.clj |    3 ++-
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/clj/clojure/data.clj b/src/clj/clojure/data.clj
index 6e8dbcf..345b234 100644
--- a/src/clj/clojure/data.clj
+++ b/src/clj/clojure/data.clj
@@ -30,6 +30,22 @@
      (vec (repeat (apply max (keys m))  nil))
      m)))
 
+(defn- diff-associative-key
+  "Diff associative things a and b, comparing only the key k."
+  [a b k]
+  (let [va (get a k)
+        vb (get b k)
+        [a* b* ab] (diff va vb)
+        in-a (contains? a k)
+        in-b (contains? b k)
+        same (and in-a in-b
+                  (or (not (nil? ab))
+                      (and (nil? va) (nil? vb))))]
+    [(when (and in-a (or (not (nil? a*)) (not same))) {k a*})
+     (when (and in-b (or (not (nil? b*)) (not same))) {k b*})
+     (when same {k ab})
+     ]))
+
 (defn- diff-associative
   "Diff associative things a and b, comparing only keys in ks."
   [a b ks]
@@ -38,7 +54,7 @@
      (doall (map merge diff1 diff2)))
    [nil nil nil]
    (map
-    (fn [k] (map #(when % {k %}) (diff (get a k) (get b k))))
+    (partial diff-associative-key a b)
     ks)))
 
 (defn- diff-sequential
diff --git a/test/clojure/test_clojure/data.clj b/test/clojure/test_clojure/data.clj
index 9bab766..5a241e0 100644
--- a/test/clojure/test_clojure/data.clj
+++ b/test/clojure/test_clojure/data.clj
@@ -27,5 +27,6 @@
        [#{1} #{3} #{2}] (HashSet. [1 2]) (HashSet. [2 3])
        [nil nil [1 2]] [1 2] (into-array [1 2])
        [nil nil [1 2]] (into-array [1 2]) [1 2]
-       [{:a {:c [1]}} {:a {:c [0]}} {:a {:c [nil 2] :b 1}}] {:a {:b 1 :c [1 2]}} {:a {:b 1 :c [0 2]}}))
+       [{:a {:c [1]}} {:a {:c [0]}} {:a {:c [nil 2] :b 1}}] {:a {:b 1 :c [1 2]}} {:a {:b 1 :c [0 2]}}
+       [{:a nil} {:a false} {:b nil :c false}] {:a nil :b nil :c false} {:a false :b nil :c false}))
 
-- 
1.7.9.5
Comment by Andy Fingerhut [ 12/Jun/12 12:43 PM ]

Philip, thanks for writing that patch. Could you please attach it as a file to this ticket, instead of copying and pasting it into a comment? Instructions are under the heading "Adding patches" on this page:

http://dev.clojure.org/display/design/JIRA+workflow

Rich Hickey's policy is only to include code in Clojure that is written by those who have signed a contributor agreement. You can find out more at http://clojure.org/contributing

Comment by Philip Aston [ 12/Jun/12 2:51 PM ]

Thanks Andy. Patch attached:

0001-clojure.data-diff-cope-with-falsey-values-in-maps.patch

I'll send in a CA.

Comment by Philip Aston [ 16/Jun/12 5:27 AM ]

CA snail-mailed yesterday, I guess it will take a week to arrive.

Comment by Philip Aston [ 23/Jun/12 5:00 AM ]

I now have a CA in place.

Comment by Stuart Halloway [ 20/Jul/12 4:51 PM ]

Yeah, this should be fixed.

Comment by Aaron Bedra [ 14/Aug/12 9:42 PM ]

Patch applies cleanly against 4004d267e124f12b65b0d7fb6522f32a75e3c4fb. Submitter is a confirmed CA signer.





[CLJ-1009] make print-table org mode compatible Created: 08/Jun/12  Updated: 18/Aug/12  Resolved: 18/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Enhancement Priority: Minor
Reporter: Stuart Halloway Assignee: Stuart Halloway
Resolution: Completed Votes: 2
Labels: None

Attachments: Text File clj-1009-print-table-org-mode-patch3.txt     Text File print-table-org-mode.txt    
Patch: Code
Approval: Ok

 Comments   
Comment by Andy Fingerhut [ 08/Jun/12 10:39 PM ]

Patch clj-1009-print-table-org-mode-patch2.txt dated June 8, 2012 is the same as Stuart Halloway's print-table-org-mode.txt of the same date, except a couple of tests have been added. His code changes look correct to me.

Comment by Aaron Bedra [ 14/Aug/12 8:22 PM ]

This is not quite correct. the header separator in org-mode is

|--+--+--|
not
+--+--+

Comment by Andy Fingerhut [ 15/Aug/12 10:29 AM ]

clj-1009-print-table-org-mode-patch3.txt dated Aug 15, 2012 is same as the previous -patch2.txt version of Jun 8, 2012 (now deleted as obsolete), except it corrects the header separator as identified by Aaron Bedra.

Comment by Andy Fingerhut [ 15/Aug/12 10:31 AM ]

Presumptuously changing approval from Incomplete back to Vetted, as it was before Aaron Bedra described a problem with the patch, and I updated the patch to address his comment. Feel free to apply the smackdown if necessary.

Comment by Aaron Bedra [ 15/Aug/12 10:44 AM ]

Looks ok now. Three cheers for org-mode awesomeness!!!





[CLJ-1007] Faster empty map creation, default to PersistentArrayMap when converting an obj-map whose lenght is less than cljs.core.PersistentArrayMap/HASHMAP_THRESHOLD Created: 02/Jun/12  Updated: 07/Jun/12  Resolved: 07/Jun/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Nicola Mometto Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None

Attachments: Text File maps-improvs.patch    
Patch: Code

 Comments   
Comment by Andy Fingerhut [ 06/Jun/12 4:59 PM ]

This patch appears to be for ClojureScript, not Clojure on the JVM. Unless there is a way to change the project that a ticket belongs to after it is created, a new ticket should be created for the ClojureScript project at the link below, and this ticket closed:

http://dev.clojure.org/jira/browse/CLJS

Comment by Nicola Mometto [ 07/Jun/12 6:52 AM ]

I couldn't find any way to move this to CLJS, so i created a new ticked (http://dev.clojure.org/jira/browse/CLJS-307)

This one can be closed, thanks Andy

Comment by Andy Fingerhut [ 07/Jun/12 10:48 AM ]

It wasn't when it was filed, but now it is a duplicate of CLJS-307





[CLJ-1006] Quotient on bigdec may produce wrong result Created: 01/Jun/12  Updated: 01/Mar/13  Resolved: 09/Nov/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Major
Reporter: laurent joigny Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: bug
Environment:

Linux 3.2.0-24-generic #39-Ubuntu SMP i686 GNU/Linux


Attachments: Java Source File TestBigDecimalQuotient.java    

 Description   

Hi,

As discussed on the mailing list in the message "When arithmetic on a computer bite back" (01/jun)

There may be bug in the way quotient is implemented for bigdec.

user> (quot 1.4411518807585587E17 2) ;; correct with doubles
7.2057594037927936E16
user> (quot 1.4411518807585587E+17M 2) ;; wrong with BigDecs
72057594037927935M


Laurent



 Comments   
Comment by laurent joigny [ 01/Jun/12 5:48 PM ]

I can reproduce the bug when using BigDecimal constructor on String.
See attached file for a test class.

More infos :
java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.1) (6b24-1.11.1-4ubuntu3)
OpenJDK Client VM (build 20.0-b12, mixed mode, sharing)

Comment by laurent joigny [ 01/Jun/12 5:49 PM ]

A simple test file, that you can drop in Clojure sources and execute to reproduce the bug on BigDecimal constructor using String as argument.

Comment by Tassilo Horn [ 03/Jun/12 4:30 AM ]

Seems to be a general precision problem. Note that in

user> (quot 1.4411518807585587E17 2) ;; correct with doubles
7.2057594037927936E16
user> (quot 1.4411518807585587E+17M 2) ;; wrong with BigDecs
72057594037927935M

the double result is actually wrong and the bigdec one is correct. The problem which lead to the wrong conclusion is that in your calculation the input number is already wrong.

So the moral is: don't use any floating points (neither doubles nor bigdecs) for computations involving divisibility tests.

For bigdecs, you can set the math context for making computations throw exceptions if they lose precision, though:

user> (binding [*math-context* (java.math.MathContext. 1 java.math.RoundingMode/UNNECESSARY)]
	       (quot (bigdec (Math/pow 2 58)) 2))
;Division impossible
;  [Thrown class java.lang.ArithmeticException]
Comment by Stuart Sierra [ 09/Nov/12 8:49 AM ]

Not a bug. Just floating-point arithmetic.





[CLJ-1000] Performance drop in PersistentHashMap.valAt(...) in v.1.4 -- Util.hasheq(...) ? Created: 21/May/12  Updated: 01/Mar/13  Resolved: 11/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: Release 1.5

Type: Enhancement Priority: Major
Reporter: Oleksandr Shyshko Assignee: Timothy Baldridge
Resolution: Completed Votes: 1
Labels: performance
Environment:

Java(TM) SE Runtime Environment (build 1.7.0_04-b21)
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)


Attachments: File caching-hasheq-v3.diff     PNG File clj_13.png     PNG File clj_14.png    
Patch: Code
Approval: Ok

 Description   

It seems there is a 30-40% performance degradation of PersistentHashMap.valAt(...) in Clojure 1.4.
Possibly due to references to new CPU-hungry implementation of Util.hasheq(...).

I have created a demo project with more details and some profiling information here:
https://github.com/oshyshko/clj-perf



 Comments   
Comment by Christophe Grand [ 27/Nov/12 8:30 AM ]

I added a patch consisting of three commits:

  • one which adds caching to seqs, sets, maps, vectors and queues
  • one that aligns the shape of Util/hasheq on the one Util/equiv (to have a consistent behavior from the JIT compiler: without that deoptimization was more penalizing for hasheq than for equiv)
  • one that fix hasheq on records (which was non consistent with its equiv impl.) – and this commit relies on a static method introduced in the "caching hasheq" commit
Comment by Timothy Baldridge [ 30/Nov/12 12:10 PM ]

In the process of screening this, I'm not seeing much of a performance difference after applying the patch.

before patch:
user=> (-main)

Version: 1.5.0-master-SNAPSHOT
"Elapsed time: 6373.752 msecs"
"Elapsed time: 6578.037 msecs"
"Elapsed time: 6476.399 msecs"

after patch:
user=> (-main)

Version: 1.5.0-master-SNAPSHOT
"Elapsed time: 6182.699 msecs"
"Elapsed time: 6548.086 msecs"
"Elapsed time: 6496.711 msecs"

clojure 1.4:
user=> (-main)

Version: 1.4.0
"Elapsed time: 6484.234 msecs"
"Elapsed time: 6243.672 msecs"
"Elapsed time: 6248.898 msecs"

clojure 1.3
user=> (-main)

Version: 1.3.0
"Elapsed time: 3584.966 msecs"
"Elapsed time: 3618.189 msecs"
"Elapsed time: 3372.979 msecs"

I blew away my local clojure repo and re-applied the patch just to make sure, but the results are the same. Does this fix not optimize the case given in the original test project?

For reference I'm running this code:

(defn -main
[& args]

(println)
(println "Version: " (clojure-version))

(def mm 10000)

(def str-keys (map str (range mm)))
(def m (zipmap str-keys (range mm)))
(time (dotimes [i mm] (doseq [k str-keys] (m k))))

(def kw-keys (map #(keyword (str %)) (range mm)))
(def m (zipmap kw-keys (range mm)))
(time (dotimes [i mm] (doseq [k kw-keys] (m k))))

(def sym-keys (map #(symbol (str %)) (range mm)))
(def m (zipmap sym-keys (range mm)))
(time (dotimes [i mm] (doseq [k sym-keys] (m k))))

(println))

Comment by Christophe Grand [ 30/Nov/12 2:10 PM ]

Sorry, I was too quick to react on the ML (someone said it was related to hasheq caching and since I had the patch almost ready: on a project I noticed too much time spent computing hasheq on vectors).
So no, my patch doesn't improve anything with kws, syms or strs as keys. However when keys are collections, it fares better.

In 1.4, for a "regular" object, it must fails two instanceof tests before calling .hashCode().
If we make keywords and symbols implement IHashEq and reverse the test order (first IHashEq, then Number) it should improve the performance of the above benchmark – except for Strings.

Comment by Timothy Baldridge [ 30/Nov/12 2:16 PM ]

Marking as incomplete, should we also delete the patch as it seems like it should be in a different ticket?

Comment by Christophe Grand [ 03/Dec/12 10:00 AM ]

In 1.3, #'hash was going through Object.hashCode and thus was simple and fast. Plus collections hashes were cached.
In 1.4 and master, #'hash goes now through two instanceof test (Number and IHasheq in this order) before trying Object.hashCode in last resort. Plus collections hashes are not cached.
As such I'm not sure Util.hasheq inherent slowness (compared to Util.hash) and hasheq caching should be separated in two issues.

The caching-hasheq-v2.diff patchset reintroduces hashes caching for collections/hasheq and reorders the instanceof tests (to test for IHashEq before Number) and makes Keyword and Symbol implement IHashEq to branch fast in Util.hasheq.

I recommend adding a collection test to the current benchmark:

(defn -main
[& args]

(println)
(println "Version: " (clojure-version))

(def mm 10000)

(def str-keys (map str (range mm)))
(def m (zipmap str-keys (range mm)))
(time (dotimes [i mm] (doseq [k str-keys] (m k))))

(def kw-keys (map #(keyword (str %)) (range mm)))
(def m (zipmap kw-keys (range mm)))
(time (dotimes [i mm] (doseq [k kw-keys] (m k))))

(def sym-keys (map #(symbol (str %)) (range mm)))
(def m (zipmap sym-keys (range mm)))
(time (dotimes [i mm] (doseq [k sym-keys] (m k))))

(def vec-keys (map (comp (juxt keyword symbol identity) str) (range mm)))
(def m (zipmap vec-keys (range mm)))
(time (dotimes [i mm] (doseq [k vec-keys] (m k))))

(println))
Comment by Timothy Baldridge [ 03/Dec/12 10:38 AM ]

For some reason I can't get v2 to build against master. It applies cleanly, but fails to build.

Comment by Christophe Grand [ 03/Dec/12 11:30 AM ]

Timothy: I inadvertently deleted a "public" modifier before commiting... fixed in caching-hasheq-v3.diff

Comment by Timothy Baldridge [ 10/Dec/12 11:00 AM ]

I now get the following results:

Version: 1.4.0
"Elapsed time: 6281.345 msecs"
"Elapsed time: 6344.321 msecs"
"Elapsed time: 6108.55 msecs"
"Elapsed time: 36172.135 msecs"

Version: 1.5.0-master-SNAPSHOT (pre-patch)
"Elapsed time: 6126.337 msecs"
"Elapsed time: 6320.857 msecs"
"Elapsed time: 6237.251 msecs"
"Elapsed time: 18167.05 msecs"

Version: 1.5.0-master-SNAPSHOT (post-patch)
"Elapsed time: 6501.929 msecs"
"Elapsed time: 3861.987 msecs"
"Elapsed time: 3871.557 msecs"
"Elapsed time: 5049.067 msecs"

Marking as screened

Comment by Oleksandr Shyshko [ 10/Dec/12 3:53 PM ]

Please, could you add as a comment the bench result using 1.3 vs 1.5-master-post-patch?

Comment by Oleksandr Shyshko [ 11/Dec/12 2:13 PM ]

The performance with 1.5-master is now very close to 1.3 for 3/4 of the benchmark.

However, this code is still showing 43% performance drop (3411 ms VS 6030 ms – 1.3 VS 1.5-master):

(def str-keys (map str (range mm)))
(def m (zipmap str-keys (range mm)))
(time (dotimes [i mm] (doseq [k str-keys] (m k))))

Version: 1.3.0
"Elapsed time: 3411.353 msecs" <---
"Elapsed time: 3459.992 msecs"
"Elapsed time: 3365.182 msecs"
"Elapsed time: 3813.637 msecs"

Version: 1.4.0
"Elapsed time: 5710.073 msecs" <---
"Elapsed time: 5817.356 msecs"
"Elapsed time: 5774.856 msecs"
"Elapsed time: 18754.482 msecs"

Version: 1.5.0-master-SNAPSHOT
"Elapsed time: 6030.247 msecs" <---
"Elapsed time: 3372.637 msecs"
"Elapsed time: 3267.481 msecs"
"Elapsed time: 3852.927 msecs"

To reproduce:
$ git clone https://github.com/clojure/clojure.git
$ cd clojure
$ mvn install -Dmaven.test.skip=true

$ cd ..

$ git clone https://github.com/oshyshko/clj-perf.git
$ cd clj-perf
$ lein run-all





[CLJ-999] Wrong link in gh-pages index (api-index.html) Created: 18/May/12  Updated: 20/May/13  Resolved: 20/May/13

Status: Resolved
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Bogdan Popescu Assignee: Tom Faulhaber
Resolution: Completed Votes: 0
Labels: docs, documentation

Patch: None

 Description   

The api-index.html includes wrong links for the following:

  • All entries for all listed as part of clojure.test.tap
  • All entries for all listed as part of clojure.test.junit
  • All entries for all listed as part of clojure.core.protocols

The links point to pages that do not exist. The problem is that the documentation for those entries is on a "parent" page, for example, the link clojure.core.protocols-api.html#clojure.core.protocols/internal-reduce should have been clojure.core-api.html#clojure.core.protocols/internal-reduce

Not a huge bug for me, but you might want to get it fixed.

And please give my huge thanks to whoever is in charge of the documentation, I'm the developer behind Dash, a Mac OS X documentation browser, and I was in the process of creating a documentation set for Clojure, and because you guys have an index, you made my work 1000 times easier.



 Comments   
Comment by Andy Fingerhut [ 11/Mar/13 3:01 PM ]

Is this fixed now? Tom Faulhaber has regenerated the docs after the recent Clojure 1.5 release, and I think updated other things besides, so it might be.

Comment by Tom Faulhaber [ 11/Mar/13 4:43 PM ]

Nope, not fixed.

This one either slipped by me or came in right when I was changing jobs so didn't stick in my brain.

I'll take a look now. Thanks for the report, Bogdan, and thanks for the bump, Andy to get it on my radar.

Comment by Gabriel Horner [ 10/May/13 4:00 PM ]

Tom, I'm happy to help if you need it. Could you document on a wiki page how autodoc is run here? I couldn't find such a page.

Comment by Tom Faulhaber [ 20/May/13 4:18 PM ]

This is fixed with gh-pages commit 919143e (autodoc doesn't follow the regular Clojure release path since it's a website built off the source checkins).

Comment by Tom Faulhaber [ 20/May/13 4:24 PM ]

Gabriel, Thanks for the offer. I fixed this one, but may take you up on it if more come up.

There is currently no wiki page about the autodoc process but it's an excellent suggestion. I'll put it on my list to write something up. In the meantime source on the autodoc program itself is at https://github.com/tomfaulhaber/autodoc and a description of how it works is at http://tomfaulhaber.github.io/autodoc. Two caveats: (1) autodoc is currently undergoing a bunch of work (thus this bug fix) in preparation for a new release and (2) the documentation doesn't talk much about how it's used for documenting Clojure itself.





[CLJ-998] doc string for replace-first mentions non-existent replace-all Created: 18/May/12  Updated: 01/Mar/13  Resolved: 18/May/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Steve Miner Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: documentation

Attachments: Text File 0001-fix-doc-string-for-replace-first.patch    
Patch: Code

 Description   

The doc string for clojure.string/replace-first says see also replace-all, which does not exist. The actual function is simply 'replace'.



 Comments   
Comment by Andy Fingerhut [ 18/May/12 11:42 AM ]

CLJ-870 patch file CLJ-753-870-905-combined-fix3.patch dated Feb 28, 2012 fixes this issue, some other doc string issues, and fixes to the code.





[CLJ-996] alter-var-root + protocol function call results in StackOverflow Created: 16/May/12  Updated: 01/Mar/13  Resolved: 09/Nov/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: None

Type: Defect Priority: Critical
Reporter: Dmitri Naumov Assignee: Unassigned
Resolution: Declined Votes: 1
Labels: None


 Description   

The following code:

(ns example.core)

(defprotocol Foo
  (foo [x]))

(extend-protocol Foo
  Object (foo [x] x)
  nil (foo [x] nil))

(defn apply-foo [f]
  (fn [& args]
    (foo (apply f args))))

(alter-var-root #'assoc apply-foo)

takes forever to compile from emacs+swank. Running from lein repl results in following:

user=> (use 'example.core)
StackOverflowError   clojure.lang.ArrayChunk.<init> (ArrayChunk.java:28)

If delete the foo call from the apply-foo:

(defn apply-foo [f]
  (fn [& args]
    (apply f args)))

then code compiles and executes fine.

This is true not only for assoc, but also for conj, into and possibly some other functions. Note also that crashes was seen even when the protocol function is not called, but there is call to satisfies? in the apply-foo function (although it's not clear for me how to reproduce it). Tested on clojure 1.3 and 1.4.



 Comments   
Comment by Tassilo Horn [ 11/Oct/12 1:23 PM ]

Is this bug a fairly well-constructed joke? I guess so.

But this is what I think happens: You change the value of #'assoc to the function returned by apply-foo. The alter-var-root call executes (apply-foo assoc) because assoc is the current value of #'assoc, thus the new value of #'assoc is {{(fn [& args] (foo (apply assoc args)))}}. However, fn is a macro that expands to fn* and calls destructure which uses assoc!!! So now foo gets called, and probably there's another assoc call during protocol dispatch, and there you have your non-terminating recursion.

So the lesson is: Don't alter core functions unless you're exactly knowing what you do.

Comment by Stuart Sierra [ 09/Nov/12 8:42 AM ]

Not a bug. You can't alter core functions and expect things not to break.





[CLJ-990] Implement clojure.core.reducers/mapcat and some initial reducers tests Created: 10/May/12  Updated: 01/Mar/13  Resolved: 10/May/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: Release 1.5

Type: Enhancement Priority: Minor
Reporter: Tassilo Horn Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: patch, test

Attachments: Text File 0001-Implement-clojure.core.reducers-mapcat.patch     Text File 0002-Add-initial-reducers-tests.patch    
Patch: Code and Test

 Description   

The first patch implements a reducers equivalent of clojure.core/mapcat, and the second patch adds a new reducers.clj to the clojure tests that checks that map, mapcat, filter, and reduce are equivalent in clojure.core and clojure.core.reducers.



 Comments   
Comment by Rich Hickey [ 10/May/12 7:44 PM ]

applied - thanks!





[CLJ-989] clojure.org/downloads page, nightly builds link out of date Created: 08/May/12  Updated: 10/May/12  Resolved: 10/May/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Brent Millare Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: web

Patch: Code

 Description   

The clojure.org/downloads page links a page that claims to have up to date builds of Clojure's master branch at build.clojure.org.

Either build.clojure.org needs to be updated, or the link should be removed or changed to reflect the statement.

On a personal note, I'd like to be able to link to alpha/beta versions of clojure 1.5.



 Comments   
Comment by Andy Fingerhut [ 10/May/12 6:11 PM ]

Once again likely abusing the "Patch" attribute of a ticket. I've set it to Code to indicate that it is ready for screening/action, not that it actually has a patch. I suppose if you take a very broad view of patch, one that includes the English text describing the suggested web page changes to clojure.org/downloads in the description, then it does have a patch.

Comment by Alex Miller [ 10/May/12 8:14 PM ]

I have updated the link for build.clojure.org to point to https://oss.sonatype.org/content/repositories/snapshots/org/clojure/clojure/1.5.0-master-SNAPSHOT/

afaik there are no alpha/beta versions of 1.5 yet.

Comment by Andy Fingerhut [ 10/May/12 8:52 PM ]

Closing this issue – Brent or someone else can reopen if they feel the issue was not fully resolved.





[CLJ-988] the locking in MultiFn.java (synchronized methods) can cause lots of contention in multithreaded programs Created: 08/May/12  Updated: 21/Sep/12  Resolved: 21/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Enhancement Priority: Major
Reporter: Kevin Downey Assignee: Stuart Sierra
Resolution: Completed Votes: 10
Labels: bug, performance

Attachments: Text File clj-988-tests-only-patch-v1.txt     File issue988-lockless-multifn+tests-120817.diff     File issue988-lockless-multifn+tests.diff    
Patch: Code and Test
Approval: Ok

 Description   

if you call a single multimethod a lot in multithreaded code you get lots of contention for the lock on the multimethod. this contention slows things down a lot.

this is due to getMethod being synchronized. it would be great if there was some fast non-locking path through the multimethod.



 Comments   
Comment by Kevin Downey [ 08/May/12 11:30 AM ]

http://groups.google.com/group/clojure-dev/browse_thread/thread/6a8219ae3d4cd0ae?hl=en

Comment by David Santiago [ 11/May/12 6:38 AM ]

Here's a stab in the dark attempt at rewriting MultiFn to use atoms to swap between immutable copies of its otherwise mutable state.

The four pieces of the MultiFn's state that are mutable and protected by locks are now contained in the MultiFn.State class, which is immutable and contains convenience functions for creating a new one with one field changed. An instance of this class is now held in an atom in the MultiFn called state. Changes to any of these four members are now done with an atomic swap of these State objects.

The getMethod/findAndCacheBestMethod complex was rewritten to better enable the atomic logic. findAndCacheBestMethod was replaced with findBestMethod, which merely looks up the method; the caching logic was moved to getMethod so that it can be retried easily as part of the work that method does.

As it was findAndCacheBestMethod seemingly had the potential to cause a stack overflow in a perfect storm of heavy concurrent modification, since it calls itself recursively if it finds that the hierarchy has changed while it has done its work. This logic is now done in the CAS looping of getMethod, so hopefully that is not even an unlikely possibility anymore.

There is still seemingly a small race here, since the check is done of a regular variable against the value in a ref. Now as before, the ref could be updated just after you do the check, but before the MultiFn's state is updated. Of course, only the method lookup part of a MultiFn call was synchronized before; it could already change after the lookup but before the method itself executed, having a stale method finish seemingly after the method had been changed. Things are no different now in general, with the atom-based approach, so perhaps this race is not a big deal, as a stale value can't persist for long.

The patch passes the tests and Clojure and multimethods seems to work.

Comment by Kevin Downey [ 12/May/12 8:59 PM ]

this patch gets rid of the ugly lock contention issues. I have not been able to benchmark it vs. the old multimethod implementation, but looking at it, I would not be surprised if it is faster when the system is in a steady state.

Comment by Stuart Halloway [ 08/Jun/12 12:11 PM ]

This looks straightforward, except for getMethod. Can somebody with context add more discussion of how method caching works?

Also, it would be great to have tests with this one.

Comment by David Santiago [ 15/Jun/12 4:44 AM ]

Obviously I didn't write the original code, so I'm not the ideal
person to explain this stuff. But I did work with it a bit recently,
so in the hopes that I can be helpful, I'm writing down my
understanding of the code as I worked with it. Since I came to the
code and sort of reverse engineered my way to this understanding,
hopefully laying this all out will make any mistakes or
misunderstandings I may have made easier to catch and correct. To
ensure some stability, I'll talk about the original MultiFn code as it
stands at this commit:
https://github.com/clojure/clojure/blob/8fda34e4c77cac079b711da59d5fe49b74605553/src/jvm/clojure/lang/MultiFn.java

There are four pieces of state that change as the multimethod is either
populated with methods or called.

  • methodTable: A persistent map from a dispatch value (Object) to
    a function (IFn). This is the obvious thing you think it is,
    determining which dispatch values call which function.
  • preferTable: A persistent map from a dispatch value (Object) to
    another value (Object), where the key "is preferred" to the value.
  • methodCache: A persistent map from a dispatch value (Object) to
    function (IFn). By default, the methodCache is assigned the same
    map value as the methodTable. If values are calculated out of the
    hierarchy during a dispatch, the originating value and the
    ultimate method it resolves to are inserted as additional items in
    the methodCache so that subsequent calls can jump right to the
    method without recursing down the hierarchy and preference table.
  • cachedHierarchy: An Object that refers to the hierarchy that is
    reflected in the latest cached values. It is used to check if the
    hierarchy has been updated since we last updated the cache. If it
    has been updated, then the cache is flushed.

I think reset(), addMethod(), removeMethod(), preferMethod(),
prefers(), isA(), dominates(), and resetCache() are extremely
straightforward in both the original code and the patch. In the
original code, the first four of those are synchronized, and the other
four are only called from methods that are synchronized (or from
methods only called from methods that are synchronized).

Invoking a multimethod through its invoke() function will call
getFn(). getFn() will call the getMethod() function, which is
synchronized. This means any call of the multimethod will wait for and
take a lock as part of method invocation. The goal of the patch in
this issue is to remove this lock on calls into the multimethod. It in
fact removes the locks on all operations, and instead keeps its
internal mutable state by atomically swapping a private immutable
State object held in an Atom called state.

The biggest change in the patch is to the
getFn()>getMethod()>findAndCacheBestMethod() complex from the
original code. I'll describe how that code works first.

In the original code, getFn() does nothing but bounce through
getMethod(). getMethod() tries three times to find a method to call,
after checking that the cache is up to date and flushing it if it
isn't:

1. It checks if there's a method for the dispatch value in the
methodCache.

2. If not, it calls findAndCacheBestMethod() on the
dispatch value. findAndCacheBestMethod() does the following:

1. It iterates through every map entry in the method table,
keeping at each step the best entry it has found so far
(according to the hierarchy and preference tables).

2. If it did not find a suitable entry, it returns null.

3. Otherwise, it checks if the hierarchy has been changed since the cache
was last updated. If it has not changed, it inserts the method
into the cache and returns it. If it has been changed, it
resets the cache and calls itself recursively to repeat the process.

3. Failing all else, it will return the method for the default
dispatch value.

Again, remember everything in the list above happens in a call to a
synchronized function. Also note that as it is currently written,
findAndCacheBestMethod() uses recursion for iteration in a way that
grows the stack. This seems unlikely to cause a stack overflow unless
the multimethod is getting its hierarchy updated very rapidly for a
sustained period while someone else tries to call it. Nonetheless, the
hierarchy is held in an IRef that is updated independently of the
locking of the MultiFn. Finally, note that the multimethod is locked
only while the method is being found. Once it is found, the lock is
released and the method actually gets called afterwards without any
synchronization, meaning that by the time the method actually
executes, the multimethod may have already been modified in a way that
suggests a different method should have been called. Presumably this
is intended, understood, and not a big deal.

Moving on now to the patch in this issue. As mentioned, the main
change is updating this entire apparatus to work with a single atomic
swap to control concurrency. This means that all updates to the
multimethod's state have to happen at one instant in time. Where the
original code could make multiple changes to the state at different
times, knowing it was safely protected by an exclusive lock, rewriting
for atom swaps requires us to reorganize the code so that all updates
to the state happen at the same time with a single CAS.

To implement this change, I pulled the implicit looping logic from
findAndCacheBestMethod() up into getMethod() itself, and broke the
"findBestMethod" part into its own function, findBestMethod(), which
makes no update to any state while implementing the same
logic. getMethod() now has an explicit loop to avoid stack-consuming
recursion on retries. This infinite for loop covers all of the logic
in getMethod() and retries until a method is successfully found and a
CAS operation succeeds, or we determine that the method cannot be
found and we return the default dispatch value's implementation.

I'll now describe the operation of the logic in the for loop. The
first two steps in the loop correspond to things getMethod() does
"before" its looping construct in the original code, but we have to do
in the loop to get the latest values.

1. First we dereference our state, and assign this value to both
oldState and newState. We also set a variable called needWrite to
false; this is so we can avoid doing a CAS (they're not free) when
we have not actually updated the state.

2. Check if the cache is stale, and flush it if so. If the cache
gets flushed, set needWrite to true, as the state has changed.

3. Check if the methodCache has an entry for this dispatch
value. If so, we are "finished" in the sense that we found the
value we wanted. However, we may need to update the state. So,

  • If needWrite is false, we can return without a CAS, so just
    break out of the loop and return the method.
  • Otherwise, we need to update the state object with a CAS. If
    the CAS is successful, break out of the loop and return the
    target function. Otherwise, continue on the next iteration
    of the loop, skipping any other attempts to fetch the method
    later in the loop (useless work, at this point).

4. The value was not in the methodCache, so call the function
findBestMethod() to attempt to find a suitable method based on the
hierarchy and preferences. If it does find us a suitable method,
we now need to cache it ourselves. We create a new state object
with the new method cache and attempt to update the state atom
with a CAS (we definitely need a write here, so no need to check
needWrite at this point).

The one thing that is possibly questionable is the check at this
point to make sure the hierarchy has not been updated since the
beginning of this method. I inserted this here to match the
identical check at the corresponding point in
findAndCacheBestMethod() in the original code. That is also a
second check, since the cache is originally checked for freshness
at the very beginning of getMethod() in the original code. That
initial check happens at the beginning of the loop in the
patch. Given that there is no synchronization with the method
hierarchy, it is not clear to me that this second check is needed,
since we are already proceeding with a snapshot from the beginning
of the loop. Nonetheless, it can't hurt as far as I can tell, it
is how the original code worked, and I assume there was some
reason for that, so I kept the second check.

5. Finally, if findBestMethod() failed to find us a method for the
dispatch value, find the method for the default dispatch value and
return that by breaking out of the loop.

So the organization of getMethod() in the patch is complicated by two
factors: (1) making the retry looping explicit and stackless, (2)
skipping the CAS when we don't need to update state, and (3) skipping
needless work later in the retry loop if we find a value but are
unable to succeed in our attempt to CAS. Invoking a multimethod that
has a stable hierarchy and a populated cache should not even have a
CAS operation (or memory allocation) on this code path, just a cache
lookup after the dispatch value is calculated.

Comment by David Santiago [ 15/Jun/12 4:45 AM ]

I've updated this patch (removing the old version, which is entirely superseded by this one). The actual changes to MultiFn.java are identical (modulo any thing that came through in the rebase), but this newer patch has tests of basic multimethod usage, including defmulti, defmethod, remove-method, prefer-method and usage of these in a hierarchy that updates in a way interleaved with calls.

Comment by David Santiago [ 15/Jun/12 6:38 AM ]

I created a really, really simple benchmark to make sure this was an improvement. The following tests were on a quad-core hyper-threaded 2012 MBP.

With two threads contending for a simple multimethod:
The lock-based multifns run at an average of 606ms, with about 12% user, 15% system CPU at around 150%.
The lockless multifns run at an average of 159ms, with about 25% user, 3% system CPU at around 195%.

With four threads contending for a simple multimethod:
The lock-based multifns run at an average of 1.2s, with about 12% user, 15% system, CPU at around 150%.
The lockless multifns run at an average of 219ms, with about 50% user, 4% system, CPU at around 330%.

You can get the code at https://github.com/davidsantiago/multifn-perf

Comment by David Santiago [ 14/Aug/12 10:02 PM ]

It's been a couple of months, and so I just wanted to check in and see if there was anything else needed to move this along.

Also, Alan Malloy pointed out to me that my benchmarks above did not mention single-threaded performance. I actually wrote this into the tests above, but I neglected to report them at the time. Here are the results on the same machine as above (multithreaded versions are basically the same as the previous comment).

With a single thread performing the same work:
The lock-based multifns run at an average of 142ms.
The lockless multifns run at an average of 115ms.

So the lockless multimethods are still faster even in a single-threaded case, although the speedup is more modest compared to the speedups in the multithreaded cases above. This is not surprising, but it is good to know.

Comment by Stuart Sierra [ 17/Aug/12 2:58 PM ]

Screened. The approach is sound.

I can confirm similar performance measurements using David Santiago's benchmark, compared with Clojure 1.5 master as of commit f5f4faf.

Mean runtime (ms) of a multimethod when called repeatedly from N threads:

|            | N=1 | N=2 | N=4 |
|------------+-----+-----+-----|
| 1.5 master |  80 | 302 | 765 |
| lockless   |  63 |  88 | 125 |

My only concern is that the extra allocations of the State class will create more garbage, but this is probably not significant if we are already using persistent maps. It would be interesting to compare this implementation with one using thread-safe mutable data structures (e.g. ConcurrentHashMap) for the cache.

Comment by David Santiago [ 17/Aug/12 7:05 PM ]

I think your assessment that it's not significant compared to the current implementation using persistent maps is correct. Regarding the extra garbage, note that the new State is only created when the hierarchy has changed or there's a cache miss (related, obviously)... situations where you're already screwed. Then it won't have to happen again for the same method (until another change to the multimethod). So for most code, it won't happen very often.

ConcurrentHashMap might be faster, it'd be interesting to see. My instinct is to keep it as close to being "made out of Clojure" as possible. In fact, it's hard to see why this couldn't be rewritten in Clojure itself some day, as I believe Chas Emerick has suggested. Also, I would point out that two of the three maps are used from the Clojure side in core.clj. I assume they would be happier if they were persistent maps.

Funny story: I was going to point out the parts of the code that were called from the clojure side just now, and alarmingly cannot find two of the functions. I think I must have misplaced them while rewriting the state into an immutable object. Going to attach a new patch with the fix and some tests for it in a few minutes.

Comment by David Santiago [ 17/Aug/12 7:44 PM ]

Latest patch for this issue. Supersedes issue988-lockless-multifn+tests.diff as of 08/17/2012.

Comment by David Santiago [ 17/Aug/12 7:49 PM ]

As promised, I reimplemented those two functions. I also added more multimethod tests to the test suite. The new tests should definitely prevent a similar mistake. While I was at it, I went through core.clj and found all the multimethod API functions I could and ensured that there were at least some basic functionality tests for all of them. The ones I found were: defmulti, defmethod, remove-all-methods, remove-method, prefer-method, methods, get-method, prefers (Some of those already had tests from the earlier version of the patch).

Really sorry about catching this right after you vetted the patch. 12771 test assertions were apparently not affected by prefers and methods ceasing to function, but now there are 12780 to help prevent a similar error. Since you just went through it, I'm leaving the older version of the patch up so you can easily see the difference to what I've added.

Comment by Rich Hickey [ 15/Sep/12 9:05 AM ]

https://github.com/clojure/clojure/commit/83ebf814d5d6663c49c1b2d0d076b57638bff673 should fix these issues. The patch here was too much of a change to properly vet.

If you could though, I'd appreciate a patch with just the multimethod tests.

Comment by Andy Fingerhut [ 15/Sep/12 10:59 AM ]

Patch clj-988-tests-only-patch-v1.txt dated Sep 15 2012 is a subset of David Santiago's
patch issue988-lockless-multifn+tests-120817.diff dated Aug 17 2012. It includes only the tests from that patch. Applies cleanly and passes tests with latest master after Rich's read/write lock change for multimethods was committed.

Comment by Rich Hickey [ 17/Sep/12 9:20 AM ]

tests-only patch ok





[CLJ-987] pprint doesn't flush the underlying stream Created: 07/May/12  Updated: 01/Mar/13  Resolved: 14/Nov/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: David Powell Assignee: David Powell
Resolution: Completed Votes: 1
Labels: patch

Attachments: Text File 0002-pprint-now-flushes-the-underlying-stream-similarly-t.patch    
Patch: Code and Test
Approval: Ok

 Description   

Unlike prn, pprint doesn't flush the underlying stream.

pretty_writer currently overrides .flush with behaviour that pushes its own data, but does not flush the underlying stream.

pprint should behave similarly to prn with respect to flushing the underlying stream.



 Comments   
Comment by David Powell [ 07/May/12 9:43 AM ]

Test included.
Patch should ensure that flushing happens after pprint, without introducing any additional unnecessary flushes.

Comment by Stuart Halloway [ 08/Jun/12 3:11 PM ]

I am confused by the tests – they all seem to call prn, though some claim to be calling pprint.

Comment by David Powell [ 09/Jun/12 6:16 AM ]

Ah, sorry. I'd tried to remove duplicate tests before committing them, but removed the wrong ones.
Replacement patch attached:

0002-pprint-now-flushes-the-underlying-stream-similarly-t.patch

Comment by Andy Fingerhut [ 21/Jun/12 5:27 PM ]

Tempting fate once again by changing Approval from Incomplete to None after the reason it was marked as incomplete seems to have been addressed.

Comment by Stuart Sierra [ 09/Nov/12 4:07 PM ]

Screened.

Comment by Stuart Sierra [ 14/Nov/12 9:23 AM ]

Pushed in commit 1588ff3f70e864d9817bc565bd2c30b08189bc6e





[CLJ-985] make jsr166 available at build time Created: 06/May/12  Updated: 01/Mar/13  Resolved: 18/May/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Enhancement Priority: Major
Reporter: Stuart Halloway Assignee: Stuart Halloway
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File build-with-jsr166-antsetup.patch     Text File build-with-jsr166.patch    
Patch: Code
Approval: Ok

 Description   

but no runtime requirement.



 Comments   
Comment by Kevin Downey [ 07/May/12 12:46 AM ]

antsetup.sh seems to be missing?

Comment by Stuart Halloway [ 07/May/12 8:01 AM ]

and now, a patch with antsetup included

Comment by Neale Swinnerton [ 10/May/12 2:05 PM ]

You say you don't want a runtime requirement, but presumably you'll want to, at some point, run tests as part of the build so some element of runtime is required?

Comment by Stuart Halloway [ 18/May/12 8:15 PM ]

Neale: the maven "provided" scope allows use during build without runtime requirement.





[CLJ-984] Expose minKey and maxKey on PersistentTreeSet Created: 05/May/12  Updated: 07/May/12  Resolved: 07/May/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Greg Chapman Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

I have found it occasionally useful to be able to get the minimum or maximum of a sorted set. PersistentTreeMap already has public minKey and maxKey methods; I suggest adding public minKey and maxKey methods to PersistentTreeSet (which obviously will just call the relevant methods on the impl map).



 Comments   
Comment by Greg Chapman [ 05/May/12 9:09 PM ]

Actually, on further reflection, I was too hasty in opening this. first combined with seq or rseq is good enough. If I could close this I would, but I don't see a way to do so.

Comment by Andy Fingerhut [ 07/May/12 12:05 PM ]

Closing this since submitter wishes it to be.





[CLJ-982] Implement an interface? predicate to balance class? Created: 04/May/12  Updated: 09/Jun/12  Resolved: 08/Jun/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: David Rupp Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: enhancement, patch, test
Environment:

Any


Attachments: File drupp-add-interface-predicate.diff    
Patch: Code and Test

 Description   

clojure.core implements a class? predicate to detect if a thing is an instance of java.lang.Class. The attached patch implements interface? to further distinguish classes that are also interfaces. This gives us Clojure api for e.g., enumerating all interfaces a thing's base class implements; as in, (filter #(interface? %) (supers (class my-thing))).



 Comments   
Comment by Stuart Halloway [ 08/Jun/12 12:28 PM ]

I would prefer to see this, and other interop/reflective items, in a separate contrib lib.

Comment by David Rupp [ 09/Jun/12 9:08 AM ]

Thanks for the feedback, Stu. Is there an existing contrib lib for stuff like this? Or should I create one?





[CLJ-981] clojure.set/rename-keys deletes keys when there's a collision Created: 04/May/12  Updated: 15/Jun/12  Resolved: 15/Jun/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Ed Bowler Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File rename-keys-fix.patch    
Patch: Code and Test
Approval: Ok

 Description   

(set/rename-keys {:a "one" :b "two" :c "three"} {:a :b :b :a}) returns {:b "one" :c "three"}
should be {:a "two" :b "one" :c "three"}

I have created a pull request for a fix, here: https://github.com/clojure/clojure/pull/23



 Comments   
Comment by Ed Bowler [ 04/May/12 1:31 PM ]

added fix





[CLJ-977] (int \a) returns a value, (long \a) throws an exception Created: 28/Apr/12  Updated: 18/Aug/12  Resolved: 18/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Zach Tellman Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File 0001-CLJ-977-int-a-returns-a-value-long-a-throws-an-excep.patch    
Patch: Code
Approval: Ok

 Description   

As described in the summary, calling (long ...) on a character throws a ClassCastException. I know the semantics surrounding numbers has changed a bit, but I think it would be nice for this to be consistent.



 Comments   
Comment by Scott Lowe [ 12/May/12 10:45 PM ]

Attached a patch. 0001-CLJ-977-int-a-returns-a-value-long-a-throws-an-excep.patch 13/May/12

Comment by Aaron Bedra [ 14/Aug/12 8:11 PM ]

Patch applies cleanly against 4004d267e124f12b65b0d7fb6522f32a75e3c4fb. Submitter is a confirmed CA signer.





[CLJ-975] inconsistent destructuring behaviour when using nested maps Created: 19/Apr/12  Updated: 18/May/12  Resolved: 18/May/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.1, Release 1.2, Release 1.3, Release 1.4, Release 1.5
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Sunil S Nandihalli Assignee: Hubert Iwaniuk
Resolution: Completed Votes: 0
Labels: None
Environment:

This should happen on any system. I have tested it on macs in version 1.4 and 1.2.1


Attachments: Text File CLJ-975-test.patch    
Patch: Code and Test
Approval: Ok

 Description   

The way destructuring happens should not be affected by the fact that I have the same w at two-levels.
user>> (let [{{a :a b :b :as w} :c a1 :a b1 :b :as w} {:a 10 :b 20 :c {:a 30 :b 40}}] {:a a :b b :b1 b1 :a1 a1})
{:a 30, :b 40, :b1 40, :a1 30} <- unexpected behaviour.....

user>> (let [{{a :a b :b :as w} :c a1 :a b1 :b :as w1} {:a 10 :b 20 :c {:a 30 :b 40}}] {:a a :b b :b1 b1 :a1 a1})
{:a 30, :b 40, :b1 20, :a1 10} <- expected behaviour ..

Even having the :as things from both should not affet how others are destructured.. The email thread talking about the same is here

https://groups.google.com/forum/?fromgroups#!topic/clojure/3z3JtXhcDB0



 Comments   
Comment by Hubert Iwaniuk [ 20/Apr/12 2:18 PM ]

Test to reproduce reported issue and code fixing it.

Comment by Hubert Iwaniuk [ 20/Apr/12 3:36 PM ]

Test to reproduce and clearly visualise this issue as well as code fixing it included.

Comment by Stuart Halloway [ 18/May/12 9:11 AM ]

A less eye-bleeding example

(let [{{inner :a :as w} :c outer :a :as w}
      {:a 10 :c {:a 30}}]
  outer)




[CLJ-974] TAP test runner broken in clojure.test Created: 15/Apr/12  Updated: 15/Apr/12  Resolved: 15/Apr/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Major
Reporter: John Szakmeister Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None

Attachments: File fix-tap-test-runner.diff    
Patch: Code

 Description   

While playing with clojure.test, I discovered that the TAP test runner is broken. Some calls were missing parameters, some had too many, and the test runner was missing a handler for failures (versus errors).



 Comments   
Comment by Andy Fingerhut [ 15/Apr/12 12:53 PM ]

Does this patch fix all of the issues mentioned in CLJ-954? If so, let me know and we can mark one of them as a duplicate, making sure the patch is on the one that isn't dup'ed.

Comment by John Szakmeister [ 15/Apr/12 6:43 PM ]

Shame on me. I didn't search the issue tracker. Sorry about that Andy. Yes, this does fix CLJ-954. I close this as a duplicate of the other and attach the patch there.

Thanks Andy!

Comment by John Szakmeister [ 15/Apr/12 6:44 PM ]

Bah, I don't have permissions to do that. Can you mark this as a duplicate? Thanks again!

Comment by Andy Fingerhut [ 15/Apr/12 6:53 PM ]

Closed as duplicate of CLJ-954. Patch has been attached to that ticket now.





[CLJ-973] doc for *data-readers* is wrong about the format for data_readers.clj Created: 14/Apr/12  Updated: 14/Apr/12  Resolved: 14/Apr/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Steve Miner Assignee: Stuart Halloway
Resolution: Completed Votes: 0
Labels: documentation

Attachments: Text File 0001-CLJ-973-doc-for-data-readers.patch    
Approval: Ok

 Description   

Sometime recently, the format for data_readers.clj changed to require a read-time literal map instead of pairs of symbols. The doc string for *data-readers* should be updated to reflect the change.



 Comments   
Comment by Steve Miner [ 14/Apr/12 9:59 AM ]

Fixed doc string for *data-readers*





[CLJ-972] Document changes between Clojure 1.3 and 1.4 Created: 11/Apr/12  Updated: 15/Apr/12  Resolved: 15/Apr/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Task Priority: Minor
Reporter: Clinton R. Nixon Assignee: Stuart Halloway
Resolution: Completed Votes: 1
Labels: None

Attachments: Text File changes-1.4.patch    
Approval: Ok

 Description   

The changes between Clojure 1.3 and 1.4 need to be documented before release.






[CLJ-967] java.io/do-copy can still garble multibyte characters on IBM JDK 1.5 and 1.6 Created: 07/Apr/12  Updated: 01/Mar/13  Resolved: 01/Mar/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.2, Release 1.3, Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Andy Fingerhut Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None
Environment:

At least Linux + IBM JDK 1.5, and Linux + IBM JDK 1.6


Attachments: Text File clj-886-improved-fix-for-ibm-jdks-patch2.txt     Text File clj-967-disable-failing-io-copy-tests-on-ibm-jdk-16-patch1.txt    
Patch: Code and Test
Approval: Not Approved

 Description   

Same issue as CLJ-886, but while the patch applied for that issue fixes the problem for many OS/JDK combos, there appear to be differences in how surrogate pair characters are handled in some OS/JDK combos. In particular, at least Linux + IBM JDK 1.5 and Linux + IBM JDK 1.6 still fail the tests checked in for do-copy.



 Comments   
Comment by Andy Fingerhut [ 07/Apr/12 9:32 AM ]

clj-886-improved-fix-for-ibm-jdks-patch2.txt dated Apr 7 2012 makes the tests pass with Linux + IBM JDK 1.5, as well as these other combos tested:

Linux + Oracle JDK 1.7
Linux + IBM JDK 1.5
Mac OS X 10.6.8 + Oracle/Apple JDK 1.6

There are still failing tests for Linux + IBM JDK 1.6. This patch currently skips the failing tests whenever the java.vendor is "IBM Corporation" and java.version is "1.6.0", so that "ant" succeeds. It is easy enough to modify the patch so that the failing tests are kept as a bright shining reminder. Let me know if that would be preferred – it just involves removing the function ibm-jdk16, and simplifying where it is called after replacing it with false.

Comment by Stuart Halloway [ 18/May/12 9:30 AM ]

Not sure if we should be in the business of building JDK-specific workarounds into our IO library, but marking this as screened.

Option B is to leave the code as-is and only disable the tests. Rich?

Comment by Rich Hickey [ 18/May/12 2:42 PM ]

Please disable the tests. We shouldn't be doing such workarounds.

Comment by Andy Fingerhut [ 19/May/12 2:50 AM ]

clj-967-disable-failing-io-copy-tests-on-ibm-jdk-16-patch1.txt dated May 19, 2012 disables tests of clojure.java.io/copy that fail with IBM JDK 1.6.0. It makes minor changes to the clojure.java.io code file, but these are only to eliminate uses of reflection, and to make a few of the versions of do-copy share more of their implementation code.

Tested that all results are good on Mac OS X 10.6.8 + Oracle/Apple JDK 1.6.0 and Ubuntu 11.10 + Oracle JDK 1.7.0, including that the number of tests run are identical to before this patch. Only 2 tests are disabled on IBM JDK 1.6.0, and all of the rest pass before and after these changes.

Comment by Andy Fingerhut [ 19/May/12 3:22 AM ]

Hoping that I'm not out of line changing approval from Incomplete to None after attaching a patch that should address the reason it was marked incomplete. The only other way to get a ticket out of Incomplete state is for a core team member to do it for me, which seems like busy-work.

Comment by Andy Fingerhut [ 30/Aug/12 2:13 PM ]

Any comments from Rich or other screeners on the status of this one? Just curious, since it seemed to have been screened, and then quietly tossed back into the unscreened pile. Is it considered undesirable to disable selected tests for a particular JDK as the patch clj-967-disable-failing-io-copy-tests-on-ibm-jdk-16-patch1.txt does? My motivation was to selectively disable only the tests that fail, and only on the JDK where they fail, leaving all passing tests to continue to run wherever possible.





[CLJ-966] Add support for marker protocols Created: 05/Apr/12  Updated: 18/Aug/12  Resolved: 18/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Enhancement Priority: Minor
Reporter: Nicola Mometto Assignee: Unassigned
Resolution: Completed Votes: 2
Labels: None

Attachments: File CLJ-966-additional-marker-tests-APPLY-AFTER.diff     File marker-protocols.diff    
Patch: Code and Test
Approval: Ok

 Description   

The attached patch adds support to marker protocols, for example

(defprotocol Sequential
"marker protocol indicating a sequential type")



 Comments   
Comment by Jonas Enlund [ 07/Apr/12 1:20 PM ]

Marker protocols are supported and used in ClojureScript.

Comment by Kevin Downey [ 15/Aug/12 2:23 PM ]

what are the uses for marker protocols? I know there are marker interfaces in java, but is it a pattern we want to carry forward?

Comment by Fogus [ 15/Aug/12 2:40 PM ]

Nice and simple. Tested with:

(defprotocol P (hi [_]))
(defprotocol M)
(deftype T [a] M P (hi [_] "hi there"))
(satisfies? P (T. 1))
(satisfies? M (T. 1))
(hi (T. 1))
(defprotocol M2 "marker for 2")
(extend-type T M2)
(satisfies? M2 (T. 1))

Similar tests are included in the additional patch file as test cases. This additional patch file should be applied after the feature's main patch file.





[CLJ-965] clojure.org/patches should have link to JIRA workflow wiki page added, and most content removed Created: 04/Apr/12  Updated: 10/May/12  Resolved: 10/May/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Andy Fingerhut Assignee: Unassigned
Resolution: Completed Votes: 1
Labels: documentation

Patch: Code

 Description   

http://groups.google.com/group/clojure-dev/browse_frm/thread/12e90e460aec29cb

Relevant text supporting this suggestion copied below:

[1] http://dev.clojure.org/display/design/JIRA+workflow

Only a few have permission to edit this page:

[2] http://clojure.org/patches

I have carefully reviewed the content of those two side by side, section by section, and it seems to me that they are either identical, or [1] is more up to date.

I am not proposing getting rid of [2], but instead do this:

Keep the first section headed "Submitting patches to Clojure and Clojure Contrib" exactly as it is now.

Immediately under the heading "So You Have an Idea...", put a single link, perhaps with one sentence or phrase, that points at [1]. Delete all other text from there down on [2]. You will lose nothing worth saving, and you will save future confusion as what is now [2] gets more and more stale.



 Comments   
Comment by Andy Fingerhut [ 04/Apr/12 2:32 PM ]

I am probably abusing the "Patch" attribute of this ticket. I've set it to Code to indicate that it is ready for screening/action, not that it actually has a patch. I suppose if you take a very broad view of patch, one that includes the English text describing the suggested web page changes to clojure.org/patches in the description, then it does have a patch.

Comment by Andy Fingerhut [ 24/Apr/12 4:09 PM ]

Another link that would be nice to update: On http://clojure.org/contributing there is a link with text "preferred process for submitting" that links to http://clojure.org/patches. It should link to http://dev.clojure.org/display/design/JIRA+workflow instead.

Comment by Alex Miller [ 10/May/12 8:38 PM ]

I have boldly made the suggested changes to the patches page as it seems imminently reasonable to avoid duplicating the more maintained version of the content. I added the sentence:

"Great! For more info on the process of creating issues in JIRA, creating and filing patches, tracking, screening and vetting patches, please visit the JIRA workflow page on the dev wiki." with a big wide link target to the jira workflow page.

If the powers that be deem my changes to be unsuitable, the powers that be can revert to the prior version here:
http://clojure.org/page/diff/patches/270799794

Comment by Alex Miller [ 10/May/12 8:40 PM ]

I also changed the link on http://clojure.org/contributing per the other comment.

Comment by Andy Fingerhut [ 10/May/12 8:49 PM ]

Between the two of us, Alex, we have just enough permissions to make the change to clojure.org and close the ticket Thanks!





[CLJ-964] test-clojure/rt.clj has undeclared dependency on clojure.set Created: 31/Mar/12  Updated: 18/Aug/12  Resolved: 18/Aug/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Trivial
Reporter: David Miller Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: test

Attachments: Text File clj-964-add-require-of-clojure-set-patch1.txt    
Patch: Code
Approval: Ok

 Description   

In test-clojure/rt.clj, the test last-var-wins-for-core evaluates #'clojure.set/subset?. This fails unless clojure.set has been loaded. In the normal run of the test suite, this dependency is satisfied by test-clojure/core-set being loaded first.



 Comments   
Comment by Andy Fingerhut [ 31/Mar/12 8:47 PM ]

clj-964-add-require-of-clojure-set-patch1.txt dated March 31, 2012 applies cleanly as of latest master. It simply adds a require of clojure.set to test_clojure/rt.clj. I verified that if that test was the only one, it does fail without the require, and passes with it. I also verified that every other test file succeeds on its own without any further changes.

Comment by Aaron Bedra [ 14/Aug/12 8:30 PM ]

Patch applies cleanly against 4004d267e124f12b65b0d7fb6522f32a75e3c4fb. Submitter is a confirmed CA signer.





[CLJ-963] Support pretty printing namespace declarations under code-dispatch Created: 29/Mar/12  Updated: 01/Sep/12  Resolved: 01/Sep/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.2, Release 1.3
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Tom Faulhaber Assignee: Stuart Sierra
Resolution: Completed Votes: 0
Labels: patch,
Environment:

all


Attachments: File pprint-ns-patch.diff    
Patch: Code and Test
Approval: Ok
Waiting On: Rich Hickey

 Description   

Currently when you print code with an (ns ) declaration in it, the ns declaration comes out kind of messy. This patch makes that beautiful.



 Comments   
Comment by Stuart Sierra [ 24/Aug/12 8:30 AM ]

Screened.

It's not perfect, but an improvement.

Before the patch:

user=> (with-pprint-dispatch code-dispatch (pprint '(ns com.some-example.my-app (:require clojure.string [clojure.set :as set] [clojure.java.io :refer (file reader)]))))
(ns
  com.some-example.my-app
  (:require
    clojure.string
    [clojure.set :as set]
    [clojure.java.io :refer (file reader)]))
nil

After the patch:

user=> (with-pprint-dispatch code-dispatch (pprint '(ns com.some-example.my-app (:require clojure.string [clojure.set :as set] [clojure.java.io :refer (file reader)]))))
(ns com.some-example.my-app
  (:require clojure.string [clojure.set :as set]
            [clojure.java.io :refer (file reader)]))
nil




[CLJ-962] Vectors returned by subvec allow access at negative indices Created: 29/Mar/12  Updated: 18/May/12  Resolved: 18/May/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Andy Fingerhut Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File clj-962-subvec-nth-throws-on-negative-index-patch2.txt    
Patch: Code and Test
Approval: Ok

 Description   

Google group thread: https://mail.google.com/mail/?shva=1#label/clojure/1365e058eaf0d5fa

Vectors returned by subvec correctly disallow access to elements after their end, but not before their beginning.

Clojure 1.3.0
user=> (def v1 (vec (range 100)))
#'user/v1
user=> (def v2 (subvec v1 50 52))
#'user/v2
user=> (v2 3)
IndexOutOfBoundsException clojure.lang.APersistentVector$SubVector.nth (APersistentVector.java:526)
user=> (v2 -48)
2



 Comments   
Comment by Andy Fingerhut [ 29/Mar/12 10:12 AM ]

One-line simple fix. clj-962-subvec-nth-throws-on-negative-index-patch1.txt dated March 29, 2012 applies, builds, and tests cleanly on latest master. Includes a few new tests that exhibit the problem. One author has signed CA.

Comment by Alan Dipert [ 20/Apr/12 1:52 PM ]

I checked this out and it looks good to me, thank you.

Comment by Andy Fingerhut [ 10/May/12 6:29 PM ]

clj-962-subvec-nth-throws-on-negative-index-patch2.txt dated May 10, 2012 is identical to previous patch clj-962-subvec-nth-throws-on-negative-index-patch1.txt dated Mar 29, 2012, except previous one failed to apply cleanly to latest master because of some lines of context changing in the source code.





[CLJ-961] with-redefs loses a Var's root binding if the Var is thread-bound Created: 28/Mar/12  Updated: 20/Jul/12  Resolved: 20/Jul/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Jiří Maršík Assignee: Rich Hickey
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File 0001-with-redefs-saves-root-binding-instead-of-thread-loc.patch     File with_redefs_bug.clj    
Patch: Code and Test
Approval: Ok

 Description   

When a Var has an in-thread binding and I use with-redefs to temporarily alter its root binding, the value restored to the root binding after with-redefs is finished will not be the original root value, but the thread-local one. The problem is using deref instead of something like clojure.lang.Var's .getRawRoot to backup the original root values in with-derefs-fn.

I have never used with-redefs and it is very unlikely that one would use it while the Vars in question are thread-bound. However, when reading the function's definition in Joy of Clojure and later in core.clj, I did not believe this behaviour was intended.



 Comments   
Comment by Aaron Bedra [ 10/Jul/12 6:53 PM ]

I paired with Gary on this and tested the patch on my machine after it was uploaded.





[CLJ-960] Capture :column metadata (needed for ClojureScript source maps) Created: 27/Mar/12  Updated: 20/Oct/12  Resolved: 20/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Enhancement Priority: Major
Reporter: Brandon Bloom Assignee: Unassigned
Resolution: Completed Votes: 2
Labels: patch

Attachments: File CLJ-960-tests.diff     Text File columns-1.patch     Text File columns-1-v2.patch    
Patch: Code and Test
Approval: Ok

 Description   

I've begun working on implementing SourceMaps for ClojureScript. For an overview of SourceMaps, see: http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ For discussion of the feature in ClojureScript, see: https://groups.google.com/d/topic/clojure-dev/zgmXO2iM1JQ/discussion

In order to produce accurate source maps, I need column information in addition to line information from the Clojure reader.

I've made the necessary enhancement to LispReader, etc. but have some cleanup and testing left to do. I'd also like a sanity check from the core team before attaching a formal patch. You can find my work in progress here: https://github.com/brandonbloom/clojure/compare/columns



 Comments   
Comment by David Nolen [ 13/Apr/12 8:29 AM ]

You need to attach a patch so this can be assessed. Thanks!

Comment by Brandon Bloom [ 31/May/12 6:09 PM ]

Sorry David! I added a patch a while ago but forgot to add the patch label(s?) as well as leave a comment.

The patch may be out of date now, but I haven't checked. Hopefully the prescreening process will pick it up automatically run the tests.

Comment by Andy Fingerhut [ 31/May/12 6:32 PM ]

Yes, Brandon, your patch has been on the list of prescreened patches since April 15. It has always applied and built cleanly during that time. That patch label is nice to have for certain JIRA report filters, but isn't necessary for the prescreening process to pick it up.

Comment by John Szakmeister [ 27/Jul/12 5:32 AM ]

v2 now applies against the current master (191b05f1). The original patch seemed to be broken from a whitespace perspective, which was making it difficult to apply--even in a 3-way merge. The only real conflict was in Compiler.java where a "final int line" was added to CompilerException. All the tests passed.

Comment by Brandon Bloom [ 27/Jul/12 7:33 PM ]

It looks like the line field was added to CompilerException in commit 89245c68, but that commit doesn't use it for anything. Maybe a later commit uses it? Also, if we want to keep that field, can we also add a column field for patch v3?

Comment by David Nolen [ 27/Jul/12 7:36 PM ]

This patch is an enhancement. In order for this one to make any movement I believe it will need a design page outlining the problem, what this solves / alternatives.

Comment by Brandon Bloom [ 25/Aug/12 9:38 PM ]

http://dev.clojure.org/display/design/Compiler+tracking+of+columns

I added a design page, but it seems like overkill. This is a straightforward enhancement...

Comment by Rich Hickey [ 04/Oct/12 8:51 AM ]

I've applied the v2 patch (thanks!), but before we close the ticket can we please get a patch comprising some tests?

Comment by Chas Emerick [ 19/Oct/12 11:45 AM ]

Attached CLJ-960-tests.diff to verify :line and :column metadata as now provided by LineNumberingPushbackReader.

Comment by Stuart Halloway [ 19/Oct/12 3:02 PM ]

The tests are a little fragile (exact map comparison) and so will break if the reader ever does more things. In library and app projects I write tests like this using core.match, but that isn't available as a build dependency here.

Marking screened anyway.





[CLJ-956] [java.lang.ClassFormatError: Duplicate method name&signature] when using gen-class Created: 20/Mar/12  Updated: 01/Mar/13  Resolved: 09/Nov/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Daniel Ribeiro Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: AOT
Environment:

$ java -version
java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11-402-11M3527)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02-402, mixed mode)



 Description   

Hi,

When extending a class that defines a method with the signature "public void load();", I get the following load time error:

java.lang.ClassFormatError: Duplicate method name&signature

Looking into javap, I see that in fact gen-class is generating two entries for the load method. Prefix does not help in this case, as the defined load method is generated anyway.

Cheers,

  • Daniel


 Comments   
Comment by Daniel Ribeiro [ 22/Mar/12 5:10 AM ]

Hi,

I've create this small sample project to exemplify the bug ocurring: https://github.com/danielribeiro/ClojureBugReport

Cheers,

  • Daniel
Comment by Daniel Ribeiro [ 24/Mar/12 6:57 PM ]

Note that the name load is not special: it works with any abstract method, no matter the name.

Comment by Daniel Ribeiro [ 24/Mar/12 7:34 PM ]

Not a bug: I was declaring the method load, which was already defined on the abstract class. The docs do mention this:

http://clojuredocs.org/clojure_core/clojure.core/gen-class

Comment by Stuart Sierra [ 09/Nov/12 8:40 AM ]

Closed as not-a-bug.





[CLJ-954] TAP Support in clojure.test.tap Needs Updating Created: 15/Mar/12  Updated: 18/May/12  Resolved: 18/May/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Daniel Gregoire Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: File fix-tap-test-runner.diff    
Patch: Code
Approval: Ok

 Description   

The testing-vars-str function requires one argument, but in the clojure.test.tap namespace it is currently called with zero arguments. This results in a clojure.lang.ArityException when attempting to generate TAP output with with-tap-out.

Here are links to the occurrences of this in the latest commit to clojure.test.tap:

1. https://github.com/clojure/clojure/blob/36642c984cbf52456e45a8af0a96e4b7e7417041/src/clj/clojure/test/tap.clj#L81
2. https://github.com/clojure/clojure/blob/36642c984cbf52456e45a8af0a96e4b7e7417041/src/clj/clojure/test/tap.clj#L92

After fixing this particular issue in my local copy of 1.4.0-SNAPSHOT, there appear to be other problems with this code as well (e.g., not producing correct output for failing tests). Since this code appears to be unmaintained and untested, perhaps it should live outside the main Clojure repo?



 Comments   
Comment by John Szakmeister [ 15/Apr/12 6:45 PM ]

This fixes all the known issues with the tap test runner.





[CLJ-953] drop-while doc string wrong, nil instead of logical false Created: 15/Mar/12  Updated: 30/Mar/12  Resolved: 30/Mar/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3
Fix Version/s: Release 1.4

Type: Enhancement Priority: Trivial
Reporter: Eric Schoonover Assignee: Alan Dipert
Resolution: Completed Votes: 0
Labels: documentation, patch,

Attachments: File take-while_doc_string_CLJ-953.diff    
Patch: Code
Approval: Ok

 Description   
"Returns a lazy sequence of the items in coll starting from the first
-  item for which (pred item) returns nil."
+  item for which (pred item) returns logical false."





[CLJ-952] bigdec does not properly convert a clojure.lang.BigInt Created: 12/Mar/12  Updated: 18/May/12  Resolved: 18/May/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Paul Stadig Assignee: Unassigned
Resolution: Completed Votes: 2
Labels: None

Attachments: Text File clj-952-make-bigdec-work-on-bigints-patch1.txt    
Patch: Code and Test
Approval: Ok

 Description   

bigdec handles java.math.BigInteger when converting to java.math.BigDecimal, but it does not handle clojure.lang.BigInt. Instead it treats a clojure.lang.BigInt as a Number, by casting it to long. This causes the following error:

Clojure 1.4.0-beta3
user=> (bigdec (inc (bigint Long/MAX_VALUE)))
IllegalArgumentException Value out of range for long: 9223372036854775808 clojure.lang.RT.longCast (RT.java:1123)



 Comments   
Comment by Andy Fingerhut [ 21/Mar/12 10:55 AM ]

Add a case to bigdec to handle BigInts. Also eliminate a reflection warning in the ratio case while we are in there. Paul's failing case has been added to tests, fails before the fix, and passes after. Attempted to make it as run-time efficient as possible by creating a new BigInt/toBigDecimal, patterned after the existing BigInt/toBigInteger.

Comment by Paul Stadig [ 21/Mar/12 11:51 AM ]

I was originally thinking of something like (BigDecimal. (.toBigInteger ^clojure.lang.BigInt x)). Adding a toBigDecimal method to clojure.lang.BigInt saves some object allocations and such. Probably more of a micro optimization, but it works.

Clojure 1.4.0-master-SNAPSHOT
user=> (bigdec (inc (bigint Long/MAX_VALUE)))
9223372036854775808M

Thanks, Andy!

+1

Comment by Alan Dipert [ 20/Apr/12 1:35 PM ]

Looks good to me, thanks.





[CLJ-951] Clojure 1.3+ can't intern a dynamic var Created: 09/Mar/12  Updated: 30/Nov/12  Resolved: 30/Nov/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Ryan Senior Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None

Approval: Not Approved

 Description   

In Clojure 1.3+, interned vars don't set the dynamic field in clojure.lang.Var and can't be used in a binding:

user=> (intern ns (with-meta 'dyna-var {:dynamic true}) 100)
user=> (binding [dyna-var "one hundred"] dyna-var)
;=> IllegalStateException Can't dynamically bind non-dynamic var: user/dyna-var clojure.lang.Var.pushThreadBindings (Var.java:339)

The var has the right metadata

user=> (meta #'dyna-var)
;=> {:ns #<Namespace user>, :name dyna-var, :dynamic true}

But doesn't set the dynamic flag on the var:

user=> (.isDynamic #'dyna-var)
;=> false

The push-thread-bindings function looks for the .dynamic flag. Vars created via def have it:

user=> (def ^:dynamic def-dyna-var 100)
user=> (.isDynamic #'def-dyna-var)
;=> true

Along with the metadata

user=> (meta #'def-dyna-var)
{:ns #<Namespace user>, :name def-dyna-var, :dynamic true, :line 6, :file "NO_SOURCE_PATH"}



 Comments   
Comment by Timothy Baldridge [ 30/Nov/12 3:57 PM ]

This is actually an enhancement. The Var.java and Namespace.java code does not attempt to read the metadata on the var. Instead, the compiler handles this at compile time. If you would like to see this behavior changed, feel free to bring it up on clojure-dev, and we'll discuss it.

Closing until that time.





[CLJ-950] Function literals behavior differ from that of fns Created: 08/Mar/12  Updated: 01/Mar/13  Resolved: 08/Mar/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Víctor M. Valenzuela Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: reader


 Description   

((fn [] true)) ; true
(#(true)) ; classcast exception

((fn [])) ; nil
(#()) ; ()

(some (fn [_]_) [nil false 0 1]) ; 0
(some #(%) [nil false 0 1]) ; NPE



 Comments   
Comment by Tassilo Horn [ 08/Mar/12 12:27 PM ]

This is no defect. Function literals must have a function (or macro or special form) as first symbol.
So your examples should be written like so:

user> (#(do true))
true
user> (#(do))
nil
user> (some #(do %) [nil false 0 1])
0
Comment by Víctor M. Valenzuela [ 08/Mar/12 2:10 PM ]

It makes sense. However (and correct me if I'm wrong) there should be little problem in making them fully equivalent to fns, resulting in a more concise and consistent API.

Please consider re-opening the issue as a feature request.

Regards - Víctor.

Comment by Tassilo Horn [ 09/Mar/12 1:26 AM ]

The reader docs at http://www.clojure.org/reader say that #() is not a replacement for (fn [] ...). You can't make it more equivalent to fn without making it much harder to understand. Let me explain that with an example.

(defn get-time []
  (System/currentTimeMillis))

(#(get-time)) ;; What's the result?

What's the result of the funcall above? Clearly, right now, it is the current system time.

So if we decided to allow to write #(true) as an alternative to (constantly true) [which is a varargs fn] or #(do true) [which is a fn of zero args], then valid values of #(get-time) where both the current system time but also the function object for get-time. Functions are values, too.

Ok, one could say that in the case of a function, #(function) is always a call, but it would make it harder to reason about what the code does for not much benefit.

Comment by Víctor M. Valenzuela [ 09/Mar/12 7:56 AM ]

You're right - satisfying my request would require to change the average use of this feature to #((some_fn %1 %2)) rather than just #(some_fn %1 %2), if we wanted #(true) to be valid. Which indeed would be barely handy.

Thank you.





[CLJ-948] It would be very useful to be able to annotate the constructors of classes created with gen-class Created: 06/Mar/12  Updated: 20/Oct/12  Resolved: 20/Oct/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: Release 1.5

Type: Enhancement Priority: Major
Reporter: Kevin Downey Assignee: Chouser
Resolution: Completed Votes: 1
Labels: None

Attachments: Text File clj-948-annotate-gen-class-constructors-patch3.txt     Text File CLJ-948.patch    
Patch: Code and Test
Approval: Ok

 Description   

gen-class currently provides a way to annotate methods, but not constructors.

when interoperating with java code that uses google juice heavily the ability to annotate constructors is required.



 Comments   
Comment by Andy Fingerhut [ 09/Mar/12 9:15 AM ]

clj-948-annotate-gen-class-constructors-patch2.txt same as Kevin's CLJ-948.patch, but with slight update so it applies cleanly to latest master as of March 9, 2012. ant builds and tests with no errors or warnings. One author Kevin Downey has signed CA.

Comment by Kevin Downey [ 09/Mar/12 9:27 AM ]

http://www.s2ki.com/s2000/uploads/gallery/1288955707/gallery_99130_32179_14062581294cd627112ab1f.gif

Comment by Andy Fingerhut [ 26/Mar/12 5:52 PM ]

clj-948-annotate-gen-class-constructors-patch3.txt on Mar 26, 2012 is no different from previous patches, except that it applies cleanly to latest master as of that date. One author Kevin Downey has signed a CA. Kevin, you don't need to thank me again. The last time gave me eye damage (only joking).

Comment by Chouser [ 18/Sep/12 12:40 AM ]

Patch is small and is a nice improvement. Tests look good and pass.





[CLJ-947] It would be very useful to be able to annotate the constructors of classes created with gen-class Created: 06/Mar/12  Updated: 01/Mar/13  Resolved: 06/Mar/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Kevin Downey Assignee: Kevin Downey
Resolution: Duplicate Votes: 0
Labels: None


 Description   

gen-class currently provides a way to annotate methods, but not constructors.

when interoperating with java code that uses google juice heavily the ability to annotate constructors is required.



 Comments   
Comment by Kevin Downey [ 06/Mar/12 10:41 AM ]

dup of CLJ-948





[CLJ-945] clojure.string/capitalize can give wrong result if first char is supplementary Created: 05/Mar/12  Updated: 01/Mar/13  Resolved: 01/Mar/13

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.2, Release 1.3, Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Minor
Reporter: Andy Fingerhut Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None
Environment:

all


Attachments: Text File capitalize-for-supplementary-chars-patch.txt    
Patch: Code and Test
Approval: Not Approved

 Description   

When the first unicode code point of a string is supplementary (i.e. requires two 16-bit Java chars to represent in UTF-16), and that first code point is changed by converting it to upper case, clojure.string/capitalize gives the wrong answer.



 Comments   
Comment by Rich Hickey [ 20/Jul/12 7:43 AM ]

Isn't this a Java bug?

Comment by Andy Fingerhut [ 20/Jul/12 12:36 PM ]

If using UTF-16 to encode Unicode strings, and making every UTF-16 code unit (i.e. Java char) individually indexable as a separate entity in strings, is such a bad design choice that you consider it a bug, then yes, this is a Java bug (and a bug in all the other systems that use UTF-16 in this way).

clojure.string/capitalize isn't using some Java capitalization method that has a bug, though. By calling (.toUpperCase (subs s 0 1)) it is not giving enough information to .toUpperCase for any implementation, Java or otherwise, to do the job correctly. It is analogous to calling toupper on the least significant 4 bits of the ASCII encoding of a letter and expecting it to return the correct answer.





[CLJ-943] When load-lib fails, a namespace is still created Created: 01/Mar/12  Updated: 15/Jun/12  Resolved: 15/Jun/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: Release 1.5

Type: Defect Priority: Major
Reporter: Hugo Duncan Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: None

Attachments: Text File 0001-Remove-namespace-if-load-lib-fails-and-namespace-did.patch    
Patch: Code and Test
Approval: Ok

 Description   

When requiring a namespace that doesn't compile, a namespace is still created. The attached patch removes the namespace on failure if the namespace wasn't already present on entry to load-lib. See the test case in the patch for repro instructions.

This is obviously a subset of having atomic loads. Would a step further in this direction, e.g. using a swapable state object within clojure.lang.Namespace be of interest?



 Comments   
Comment by Stuart Halloway [ 08/Jun/12 3:17 PM ]

Why catch Exception, not Throwable?

Comment by Stuart Halloway