[CLJ-980] Documentation for extend-type falsely implies that & is allowed in protocol fn signatures Created: 03/May/12 Updated: 19/Dec/12 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Defect | Priority: | Trivial |
| Reporter: | Charles Duffy | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | documentation | ||
| Attachments: |
|
| Patch: | Code |
| Approval: | Incomplete |
| Description |
|
The documentation for extend-type contains the following example: (extend-type MyType
Countable
(cnt [c] ...)
Foo
(bar [x y] ...)
(baz ([x] ...) ([x y & zs] ...)))
However, [x y & zs] is not a valid parameter list for a protocol fn. The documentation should be appropriately amended. |
| Comments |
| Comment by John Szakmeister [ 25/May/12 4:00 AM ] |
|
v2 of the patch is simply converts the patch to git format. I made sure that Mr. Duffy got proper attribution. I also took a stab at a simple log message. Any problems with the latter are mine, and I'm happy to fix it up if necessary. |
| Comment by Aaron Bedra [ 15/Aug/12 10:08 PM ] |
|
This doesn't update the entire doc string. The expansion is updated, but the signature section isn't. Here's what shows up. user=> (doc extend-type)
-------------------------
clojure.core/extend-type
([t & specs])
Macro
A macro that expands into an extend call. Useful when you are
supplying the definitions explicitly inline, extend-type
automatically creates the maps required by extend. Propagates the
class as a type hint on the first argument of all fns.
(extend-type MyType
Countable
(cnt [c] ...)
Foo
(bar [x y] ...)
(baz ([x] ...) ([x y & zs] ...)))
expands into:
(extend MyType
Countable
{:cnt (fn [c] ...)}
Foo
{:baz (fn ([x] ...) ([x y ...] ...))
:bar (fn [x y] ...)})
|
| Comment by Tassilo Horn [ 25/Aug/12 6:44 AM ] |
|
This is very much related to http://dev.clojure.org/jira/browse/CLJ-1024. NOTE: While varargs are not supported in protocol declarations, dynamic extension of a protocol via extend (extend-type, extend-protocol) does allow for varargs and also destructuring, cause the method impls are actually normal clojure functions. So if a Foo protocol declares a (foo [this a b c]) method, you can extend/extend-type/extend-protocol it dynamically using (foo [this & more] (do-magick)) where `a b c` are conflated into the `more` parameter. However, that doesn't work for method implementations defined by deftype, defrecord, and reify. So with respect to the facts, the example in the docstring is actually correct, so I'm not sure if it should be changed. However, what's supported in which cases should be documented better as it is right now. |
[CLJ-939] Exceptions thrown in the top level ns form are reported without file or line number Created: 24/Feb/12 Updated: 15/Dec/12 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | Release 1.3, Release 1.4 |
| Fix Version/s: | None |
| Type: | Defect | Priority: | Major |
| Reporter: | Hugo Duncan | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Attachments: |
|
| Patch: | Code |
| Approval: | Incomplete |
| Waiting On: | Rich Hickey |
| Description |
|
If there is an error in the `ns` form, an exception is thrown, which is not caught in `load`. For example, with an invalid :only clause; (ns clj14.myns (:use [clojure.core :only seq])) This generates a Don't know how to create ISeq from: clojure.lang.Symbol exception, with source file or line number. |
| Comments |
| Comment by Hugo Duncan [ 25/Feb/12 8:26 AM ] |
|
Corrected patch |
| Comment by Andy Fingerhut [ 09/Mar/12 9:26 AM ] |
|
Patch 0001-report-load-exception-with-file-and-line.diff fails build. Patch 0002-report-load-exception-with-file-and-line.diff applies, builds, and tests cleanly as of March 9, 2012. Hugo has signed a CA. |
| Comment by Andy Fingerhut [ 05/Oct/12 8:13 AM ] |
|
clj-939-report-load-exceptions-with-file-and-line-patch-v2.txt dated Oct 5 2012 is intended to be an update to Hugo Duncan's patch 0002-report-load-exceptions-with-file-and-line.diff dated Feb 25 2012. Because of Brandon Bloom's recently commited patch adding column numbers in addition to line numbers, this is not simply updating some lines of context, but I think it is correct. It would be good if Hugo could take a look at it and confirm. |
| Comment by Stuart Sierra [ 09/Nov/12 9:38 AM ] |
|
Screened. The error messages are better than what we had before. The line/column numbers are not particularly informative, probably because ns is a macro. |
| Comment by Rich Hickey [ 13/Nov/12 3:37 PM ] |
|
This patch doesn't change the reporting on any other (e.g. nested) exceptions? It looks like it might. |
[CLJ-866] Provide a clojure.test function to run a single test case with fixtures Created: 27/Oct/11 Updated: 04/May/13 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | Release 1.6 |
| Type: | Enhancement | Priority: | Major |
| Reporter: | Hugo Duncan | Assignee: | Anthony Grimes |
| Resolution: | Unresolved | Votes: | 8 |
| Labels: | None | ||
| Attachments: |
|
| Patch: | Code |
| Approval: | Incomplete |
| Description |
|
At present, clojure.test test cases are functions and can be invoked directly. However, in the case that the test relies on fixtures, this does not work. Please provide a function that can run a single test case with all fixtures applied. |
| Comments |
| Comment by Anthony Grimes [ 22/Oct/12 6:17 PM ] |
|
I just added clj-866-test-vars.patch (22/Oct/12 6:09PM). I had to implement this hackishly in Leiningen a few days ago, so I'm very excited to get this functionality in clojure.test itself. This patch adds a test-vars function that solves this problem (and is more general). You can test as many vars as you want with it, with fixtures. It works by grouping vars passed by their namespace and then running them all with appropriate fixtures applied. Being able to run a single test isn't the problem here, being able to run only specific tests is. If we wrote a function to run one test with fixtures but we actually needed to run several, just not all tests, we'd end up having to run once-fixtures more than once which is wasteful. I think test-vars is a good solution that solves both this problem and the one I just mentioned. |
| Comment by Alex Miller [ 04/May/13 9:36 AM ] |
|
This is highly useful. Could you add a test to the patch? |
[CLJ-835] defmulti doc string doesn't mention needing to be passed a var for the value of :hierarchy Created: 02/Sep/11 Updated: 19/Dec/12 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | Release 1.2 |
| Fix Version/s: | None |
| Type: | Defect | Priority: | Minor |
| Reporter: | Hugo Duncan | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 1 |
| Labels: | None | ||
| Environment: |
1.2, 1.3 beta3 |
||
| Attachments: |
|
| Patch: | Code |
| Approval: | Incomplete |
| Description |
|
The :hierarchy option for defmulti should be passed a var, but this is not mentioned in the doc string. The error message from passing the hierarchy directly is rather cryptic: Evaluation aborted on java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to clojure.lang.IRef (SOURCE_FORM_44:19). |
| Comments |
| Comment by Meikel Brandmeyer [ 14/Sep/11 3:11 PM ] |
|
Modified doctoring to clarify the usage of :hierarchy. |
| Comment by Scott Lowe [ 10/May/12 5:16 PM ] |
|
New patch: '0001-CLJ-835-Refine-doc-string-for-defmulti-hierarchy-opt.patch' 10/May/12. I've attached a new doc string patch in response to Andy Fingerhut's request posted here: https://groups.google.com/forum/?fromgroups#!topic/clojure-dev/i7H82fJYL-U Andy's request stated "Attached patch seems to have spelling mistakes, and perhaps could be worded more clearly." I hope my new patch is an improvement upon what was there. This patch supersedes '0001-Clarify-docstring-for-defmulti.patch' from 14/Sep/11. |
| Comment by Fogus [ 16/Aug/12 2:49 PM ] |
|
This is a million times better than what was there before, but (who knew!?) it could be better. A couple points of contention:
|
| Comment by Rich Hickey [ 19/Dec/12 7:58 AM ] |
|
Please leave examples out of docs strings. Use precise language. |
[CLJ-771] Move unchecked-prim casts to clojure.unchecked Created: 07/Apr/11 Updated: 13/Feb/13 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | Backlog |
| Fix Version/s: | Backlog |
| Type: | Enhancement | Priority: | Minor |
| Reporter: | Alexander Taggart | Assignee: | Alexander Taggart |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Attachments: |
|
| Patch: | Code and Test |
| Approval: | Incomplete |
| Waiting On: | Rich Hickey |
| Description |
|
Per Rich's comment in
|
| Comments |
| Comment by Alexander Taggart [ 29/Apr/11 3:41 PM ] |
|
Requires that patch on |
| Comment by Stuart Sierra [ 31/May/11 10:43 AM ] |
|
Applies on master as of commit 66a88de9408e93cf2b0d73382e662624a54c6c86 |
| Comment by Rich Hickey [ 09/Dec/11 8:40 AM ] |
|
still considering when to incorporate this |
| Comment by John Szakmeister [ 19/May/12 9:36 AM ] |
|
v2 of the patch applies to master as of commit eccde24c7fb63679f00c64b3c70c03956f0ce2c3 |
| Comment by Andy Fingerhut [ 07/Sep/12 12:40 AM ] |
|
Patch clj-771-move-unchecked-casts-patch-v3.txt dated Sep 6 2012 is the same as Alexander Taggart's patch move-unchecked-casts.patch except that it has been updated to apply cleanly to latest Clojure master. |
| Comment by Andy Fingerhut [ 20/Oct/12 12:18 PM ] |
|
Patch clj-771-move-unchecked-casts-patch-v4.txt dated Oct 20 2012 is the same as Alexander Taggart's patch move-unchecked-casts.patch except that it has been updated to apply cleanly to latest Clojure master. |
| Comment by Andy Fingerhut [ 01/Jan/13 11:37 AM ] |
|
The patch clj-771-move-unchecked-casts-patch-v4.txt applies cleanly to latest master and passes all tests. Rich marked this ticket as Incomplete on Dec 9 2011 with the comment "still considering when to incorporate this" above. Is it reasonable to change it back to Vetted or Screened so it can be considered again, perhaps after Release 1.5 is made? |
| Comment by Andy Fingerhut [ 13/Feb/13 12:50 AM ] |
|
Patch clj-771-move-unchecked-casts-patch-v5.txt dated Feb 12 2013 is the same as Alexander Taggart's patch move-unchecked-casts.patch except that it has been updated to apply cleanly to latest Clojure master. |
[CLJ-766] Implicit casting behaviour of into-array differs from <primitive>-array Created: 01/Apr/11 Updated: 03/May/13 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | Release 1.3 |
| Fix Version/s: | Release 1.6 |
| Type: | Defect | Priority: | Minor |
| Reporter: | Alexander Taggart | Assignee: | Karsten Schmidt |
| Resolution: | Unresolved | Votes: | 3 |
| Labels: | None | ||
| Attachments: |
|
| Patch: | Code and Test |
| Approval: | Incomplete |
| Description |
|
Current patch: byte-short-array-ctors.diff The behavior of byte-array and short-array is inconsistent with the other <type>-array functions and with the into-array function when invoked with types other than byte or short. All of the other cases upcast to Number, then extract the primitive value, allowing this operation to succeed (assuming the value is in range). byte-array and short-array throw a ClassCastException. Example: base64v3a=> (into-array Byte/TYPE [1 2 3 4]) ;; int to byte ok #<byte[] [B@5ee04fd> base64v3a=> (byte-array [1 2 3 4]) ;; int to byte NOT ok!! ClassCastException java.lang.Long cannot be cast to java.lang.Byte clojure.lang.Numbers.byte_array (Numbers.java:1418) base64v3a=> (long-array [1 2 3 4]) ;; int to long ok #<long[] [J@3f9f4d1d> into-array (via RT.seqToTypedArray) and the other <type>-array functions all upcast to Number (via Numbers.<type>_array}}), then obtain the proper primitive value. Numbers.byte-array and Numbers.short-array do casts directly to Byte and Short (yielding the ClassCastException). The attached patch makes the Byte and Short cases match the other types and the into-array behavior. Tests are included. The submitter is a contributor. |
| Comments |
| Comment by Alexander Taggart [ 02/Apr/11 2:04 PM ] |
|
See |
| Comment by Andy Fingerhut [ 28/May/12 6:45 PM ] |
|
Some more details from Alexandar Taggart: This is not a duplicate of |
| Comment by Karsten Schmidt [ 02/Mar/13 5:11 PM ] |
|
I'd like to bump up this issue, since it'd be great if all the (xxx-array) factory functions have the same expected behavior (i.e. not throw an exception, especially not if the values are in range). The attached patch is changing the behaviour for byte-array & short-array to the same pattern used as for int/long/float/double and therefore will not throw an exception for valid (even if overflown) numbers. You can find more discussion in this thread on: https://groups.google.com/forum/?hl=en&fromgroups=#!topic/clojure/KyQrbph-zqo |
| Comment by Andy Fingerhut [ 03/Mar/13 8:11 AM ] |
|
Voting on a ticket (click the "Vote" link under the "People" heading while viewing the ticket on JIRA) may help draw attention to it, too. |
| Comment by Andy Fingerhut [ 04/Mar/13 1:08 PM ] |
|
Karsten, patches should be in the format created by the "git format-patch" command as described in the instructions under the heading "Development" on this page: http://dev.clojure.org/display/design/JIRA+workflow |
| Comment by Karsten Schmidt [ 04/Mar/13 2:05 PM ] |
|
Sorry Andy, I used Atlassian SourceTree to create the patch and assumed it's in standard git format... I've removed the old one and attach a (hopefully) properly formatted one. Apologies, contributing-beginners-luck! |
| Comment by Stuart Halloway [ 30/Mar/13 8:52 AM ] |
|
While investigating this, I noticed that long-array coerces across type, e.g. (seq (long-array [1.0])) => (1) Is this what we want? I don't think so. |
| Comment by Stuart Halloway [ 30/Mar/13 8:53 AM ] |
|
I agree that all the numeric array constructors should work the same way, but I am not sue we should adopt long-array's approach, which allows coercion from float to integer types. |
| Comment by Alex Miller [ 03/May/13 8:31 PM ] |
|
I think the patch approach is valid. However, the patch does not cover the same problem in the 2-arity version of byte_array and short_array (when a size is supplied). Please update the patch to include a fix in the 2-arity version of byte_array and short_array and tests for the same. Ex: (byte-array 1 [1]). Also, there is a whitespace issue in the patch - please just use spaces! /Users/alex/work/code/clojure/.git/rebase-apply/patch:24: space before tab in indent. ret[i] = ((Number)s.first()).byteValue(); warning: 1 line adds whitespace errors. Re Stuart's comments, I don't think that's in the scope of this ticket or solution. |
| Comment by Alex Miller [ 03/May/13 8:32 PM ] |
|
Sending back to Karsten for the requested patch updates. |
[CLJ-445] Method/Constructor resolution does not factor in widening conversion of primitive args Created: 29/Sep/10 Updated: 20/Feb/12 |
|
| Status: | In Progress |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | Reviewed Backlog |
| Type: | Enhancement | Priority: | Major |
| Reporter: | Alexander Taggart | Assignee: | Alexander Taggart |
| Resolution: | Unresolved | Votes: | 2 |
| Labels: | None | ||
| Attachments: |
|
| Approval: | Incomplete |
| Description |
|
Problem: Examples: user=> (Integer. (byte 0)) java.lang.IllegalArgumentException: No matching ctor found for class java.lang.Integer (NO_SOURCE_FILE:0) </code></pre> The above occurs because there is no Integer(byte) constructor, though it should match on Integer(int). <pre><code>user=> (bit-shift-left (byte 1) 1) Reflection warning, NO_SOURCE_PATH:3 - call to shiftLeft can't be resolved. 2 In the above, a call is made via reflection to Numbers.shiftLeft(Object, Object) and its associated auto-boxing, instead of directly to the perfectly adequate Numbers.shiftLeft(long, int). Workarounds: Ancillary benefits of fixing: |
| Comments |
| Comment by Assembla Importer [ 23/Oct/10 6:43 PM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/445 |
| Comment by Assembla Importer [ 23/Oct/10 6:43 PM ] |
|
ataggart said: [file:b6gDSUZOur36b9eJe5cbCb] |
| Comment by Assembla Importer [ 23/Oct/10 6:43 PM ] |
|
ataggart said: Also fixes #446. |
| Comment by Stuart Halloway [ 03/Dec/10 12:50 PM ] |
|
The patch is causing a test failure [java] Exception in thread "main" java.lang.IllegalArgumentException:
More than one matching method found: equiv, compiling:(clojure/pprint/cl_format.clj:428)
Can you take a look? |
| Comment by Stuart Halloway [ 28/Jan/11 12:30 PM ] |
|
The failing test happens when trying to find the correct equiv for signature (Number, long). Is the compiler wrong to propose this signature, or is the resolution method wrong in not having an answer? (It thinks two signatures are tied: (Object, long) and (Number, Number).) Exception in thread "main" java.lang.IllegalArgumentException: More than one matching method found: equiv, compiling:(clojure/pprint/cl_format.clj:428) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6062) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6050) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.access$100(Compiler.java:35) at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5492) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6055) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6043) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6043) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler$IfExpr$Parser.parse(Compiler.java:2372) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6055) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6043) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3277) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6057) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5231) at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5527) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6055) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6043) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5231) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6055) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler$IfExpr$Parser.parse(Compiler.java:2385) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6055) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5231) at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5527) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6055) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6043) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler$IfExpr$Parser.parse(Compiler.java:2385) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6055) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5231) at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5527) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6055) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6043) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5231) at clojure.lang.Compiler$FnMethod.parse(Compiler.java:4667) at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3397) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6053) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6043) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.access$100(Compiler.java:35) at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:480) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6055) at clojure.lang.Compiler.analyze(Compiler.java:5866) at clojure.lang.Compiler.analyze(Compiler.java:5827) at clojure.lang.Compiler.eval(Compiler.java:6114) at clojure.lang.Compiler.load(Compiler.java:6545) at clojure.lang.RT.loadResourceScript(RT.java:340) at clojure.lang.RT.loadResourceScript(RT.java:331) at clojure.lang.RT.load(RT.java:409) at clojure.lang.RT.load(RT.java:381) at clojure.core$load$fn__1427.invoke(core.clj:5308) at clojure.core$load.doInvoke(core.clj:5307) at clojure.lang.RestFn.invoke(RestFn.java:409) at clojure.pprint$eval3969.invoke(pprint.clj:46) at clojure.lang.Compiler.eval(Compiler.java:6110) at clojure.lang.Compiler.load(Compiler.java:6545) at clojure.lang.RT.loadResourceScript(RT.java:340) at clojure.lang.RT.loadResourceScript(RT.java:331) at clojure.lang.RT.load(RT.java:409) at clojure.lang.RT.load(RT.java:381) at clojure.core$load$fn__1427.invoke(core.clj:5308) at clojure.core$load.doInvoke(core.clj:5307) at clojure.lang.RestFn.invoke(RestFn.java:409) at clojure.core$load_one.invoke(core.clj:5132) at clojure.core$load_lib.doInvoke(core.clj:5169) at clojure.lang.RestFn.applyTo(RestFn.java:143) at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:77) at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28) at clojure.core$apply.invoke(core.clj:602) at clojure.core$load_libs.doInvoke(core.clj:5203) at clojure.lang.RestFn.applyTo(RestFn.java:138) at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:77) at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28) at clojure.core$apply.invoke(core.clj:604) at clojure.core$use.doInvoke(core.clj:5283) at clojure.lang.RestFn.invoke(RestFn.java:409) at clojure.main$repl.doInvoke(main.clj:196) at clojure.lang.RestFn.invoke(RestFn.java:422) at clojure.main$repl_opt.invoke(main.clj:267) at clojure.main$main.doInvoke(main.clj:362) at clojure.lang.RestFn.invoke(RestFn.java:409) at clojure.lang.Var.invoke(Var.java:401) at clojure.lang.AFn.applyToHelper(AFn.java:163) at clojure.lang.Var.applyTo(Var.java:518) at clojure.main.main(main.java:37) Caused by: java.lang.IllegalArgumentException: More than one matching method found: equiv at clojure.lang.Reflector.getMatchingParams(Reflector.java:639) at clojure.lang.Reflector.getMatchingParams(Reflector.java:578) at clojure.lang.Reflector.getMatchingMethod(Reflector.java:569) at clojure.lang.Compiler$StaticMethodExpr.<init>(Compiler.java:1439) at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:896) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6055) ... 115 more |
| Comment by Alexander Taggart [ 08/Feb/11 6:27 PM ] |
|
In working on implementing support for vararg methods, I found a number of flaws with the previous solutions. Please disregard them. I've attached a single patch (reflector-compiler-numbers.diff) which is a rather substantial overhaul of the Reflector code, with some enhancements to the Compiler and Numbers code. The patch notes:
|
| Comment by Alexander Taggart [ 10/Feb/11 7:35 PM ] |
|
Updated patch to fix a bug where a concrete class with multiple identical Methods (e.g., one from an interface, another from an abstract class) would result in ambiguity. Now resolved by arbitrary selection (this is what the original code did as well albeit not explicitly). |
| Comment by Alexander Taggart [ 25/Feb/11 9:29 PM ] |
|
Updated patch to work with latest master branch. |
| Comment by Stuart Halloway [ 06/Mar/11 1:54 PM ] |
|
patch appears to be missing test file clojure/test_clojure/reflector.clj. |
| Comment by Alexander Taggart [ 06/Mar/11 2:39 PM ] |
|
Bit by git. Patch corrected to contain clojure.test-clojure.reflector. |
| Comment by Stuart Halloway [ 11/Mar/11 10:30 AM ] |
|
Rich: I verified that the patch applied but reviewed only briefly, knowing you will want to go over this one closely. |
| Comment by Stuart Halloway [ 11/Mar/11 10:55 AM ] |
|
After applying this patch, I am getting method missing errors: java.lang.NoSuchMethodError: clojure.lang.Numbers.lt(JLjava/lang/Object;)
but only when using compiled code, e.g. the same code works in the REPL and then fails after compilation. Haven't been able to isolate an example that I can share here yet, but hoping this will cause someone to have an "a, hah" moment... |
| Comment by Alexander Taggart [ 02/Apr/11 12:55 PM ] |
|
The patch now contains only the minimal changes needed to support widening conversion. Cleanup of Numbers overloads, etc., can wait until this patch gets applied. The vararg support is in a separate patch on CLJ-440. |
| Comment by Christopher Redinger [ 15/Apr/11 12:50 PM ] |
|
Please test patch |
| Comment by Christopher Redinger [ 21/Apr/11 11:02 AM ] |
|
FYI: Patch applies cleanly on master and all tests pass as of 4/21 (2011) |
| Comment by Christopher Redinger [ 22/Apr/11 9:57 AM ] |
|
This work is too big to take into the 1.3 beta right now. We'll revisit for a future release. |
| Comment by Alexander Taggart [ 28/Apr/11 1:19 PM ] |
|
To better facilitate understanding of the changes, I've broken them up into two patches, each with a number of isolable, incremental commits: reorg-reflector.patch: Moves the reflection/invocation code from Compiler to Reflector, and eliminates redundant code. The result is a single code base for resolving methods/constructors, which will allow for altering that mechanism without excess external coordination. This contains no behaviour changes. prim-conversion.patch: Depends on the above. Alters the method/constructor resolution process:
This also provides a base to add further features, e.g., CLJ-666. |
| Comment by Alexander Taggart [ 29/Apr/11 3:01 PM ] |
|
It's documented in situ, but here are the conversion rules that the reflector uses to find methods:
|
| Comment by Alexander Taggart [ 10/May/11 3:13 PM ] |
|
prim-conversion-update-1.patch applies to current master. |
| Comment by Alexander Taggart [ 11/May/11 2:15 PM ] |
|
Created CLJ-792 for the reflector reorg. |
| Comment by Stuart Sierra [ 17/Feb/12 2:29 PM ] |
|
prim-conversion-update-1.patch does not apply as of f5bcf64. Is CLJ-792 now a prerequisite of this ticket? |
| Comment by Alexander Taggart [ 17/Feb/12 3:15 PM ] |
|
Yes, after the original patch was deemed "too big". After this much time with no action from TPTB, feel free to kill both tickets. |
| Comment by Andy Fingerhut [ 20/Feb/12 2:04 PM ] |
|
Again, not sure if this is any help, but I've tested starting from Clojure head as of Feb 20, 2012, applying clj-792-reorg-reflector-patch2.txt attached to CLJ-792, and then applying clj-445-prim-conversion-update-2-patch.txt attached to this ticket, and the result compiles and passes all but 2 tests. I don't know whether those failures are easy to fix or not, or whether issues may have been introduced with these patches. |
[CLJ-415] smarter assert (prints locals) Created: 29/Jul/10 Updated: 18/Nov/12 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | Approved Backlog |
| Type: | Enhancement | Priority: | Major |
| Reporter: | Assembla Importer | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 2 |
| Labels: | None | ||
| Attachments: |
|
| Approval: | Incomplete |
| Waiting On: | Rich Hickey |
| Description |
|
Here is an implementation you can paste into a repl. Feedback wanted: (defn ^{:private true} local-bindings
"Produces a map of the names of local bindings to their values."
[env]
(let [symbols (map key env)]
(zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))
(defmacro assert
"Evaluates expr and throws an exception if it does not evaluate to
logical true."
{:added "1.0"}
[x]
(when *assert*
(let [bindings (local-bindings &env)]
`(when-not ~x
(let [sep# (System/getProperty "line.separator")]
(throw (AssertionError. (apply str "Assert failed: " (pr-str '~x) sep#
(map (fn [[k# v#]] (str "\t" k# " : " v# sep#)) ~bindings)))))))))
|
| Comments |
| Comment by Assembla Importer [ 24/Aug/10 5:41 PM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/415 |
| Comment by Assembla Importer [ 24/Aug/10 5:41 PM ] |
|
alexdmiller said: A simple example I tried for illustration: user=> (let [a 1 b 2] (assert (= a b)))
#<CompilerException java.lang.AssertionError: Assert failed: (= a b)
a : 1
b : 2
|
| Comment by Assembla Importer [ 24/Aug/10 5:41 PM ] |
|
fogus said: Of course it's weird if you do something like: (let [x 1 y 2 z 3 a 1 b 2 c 3] (assert (= x y))) java.lang.AssertionError: Assert failed: (= x y) x : 1 y : 2 z : 3 a : 1 b : 2 c : 3 (NO_SOURCE_FILE:0) </code></pre> So maybe it could be slightly changed to: <pre><code>(defmacro assert "Evaluates expr and throws an exception if it does not evaluate to logical true." {:added "1.0"} [x] (when *assert* (let [bindings (local-bindings &env)] `(when-not ~x (let [sep# (System/getProperty "line.separator") form# '~x] (throw (AssertionError. (apply str "Assert failed: " (pr-str form#) sep# (map (fn [[k# v#]] (when (some #{k#} form#) (str "\t" k# " : " v# sep#))) ~bindings))))))))) </code></pre> So that. now it's just: <pre><code>(let [x 1 y 2 z 3 a 1 b 2 c 3] (assert (= x y))) java.lang.AssertionError: Assert failed: (= x y) x : 1 y : 2 (NO_SOURCE_FILE:0) :f |
| Comment by Assembla Importer [ 24/Aug/10 5:41 PM ] |
|
fogus said: Hmmm, but that fails entirely for: (let [x 1 y 2 z 3 a 1 b 2 c 3] (assert (= [x y] [a c]))). So maybe it's better just to print all of the locals unless you really want to get complicated. |
| Comment by Assembla Importer [ 24/Aug/10 5:41 PM ] |
|
jawolfe said: See also some comments in: Plus one more suggestion to add to the mix: in addition to / instead of printing the locals, how about saving them somewhere. For example, the var assert-bindings could be bound to the map of locals. This way you don't run afoul of infinite/very large sequences, and allow the user to do more detailed interrogation of the bad values (especially useful when some of the locals print opaquely). |
| Comment by Assembla Importer [ 24/Aug/10 5:41 PM ] |
|
stuart.sierra said: Another approach, which I wil willingly donate: |
| Comment by Jeff Weiss [ 15/Dec/10 1:33 PM ] |
|
There's one more tweak to fogus's last comment, which I'm actually using. You need to flatten the quoted form before you can use 'some' to check whether the local was used in the form: (defmacro assert "Evaluates expr and throws an exception if it does not evaluate to logical true." {:added "1.0"} [x] (when *assert* (let [bindings (local-bindings &env)] `(when-not ~x (let [sep# (System/getProperty "line.separator") form# '~x] (throw (AssertionError. (apply str "Assert failed: " (pr-str form#) sep# (map (fn [[k# v#]] (when (some #{k#} (flatten form#)) (str "\t" k# " : " v# sep#))) ~bindings))))))))) |
| Comment by Stuart Halloway [ 04/Jan/11 8:31 PM ] |
|
I am holding off on this until we have more solidity around http://dev.clojure.org/display/design/Error+Handling. (Considering, for instance, having all exceptions thrown from Clojure provide access to locals.) When my pipe dream fades I will come back and screen this before the next release. |
| Comment by Stuart Halloway [ 28/Jan/11 1:14 PM ] |
|
Why try to guess what someone wants to do with the locals (or any other context, for that matter) when you can specify a callback (see below). This would have been useful last week when I had an assertion that failed only on the CI box, where no debugger is available. Rich, at the risk of beating a dead horse, I still think this is a good idea. Debuggers are not always available, and this is an example of where a Lisp is intrinsically capable of providing better information than can be had in other environments. If you want a patch for the code below please mark waiting on me, otherwise please decline this ticket so I stop looking at it. (def ^:dynamic *assert-handler* nil) (defn ^{:private true} local-bindings "Produces a map of the names of local bindings to their values." [env] (let [symbols (map key env)] (zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols))) (defmacro assert [x] (when *assert* (let [bindings (local-bindings &env)] `(when-not ~x (let [sep# (System/getProperty "line.separator") form# '~x] (if *assert-handler* (*assert-handler* form# ~bindings) (throw (AssertionError. (apply str "Assert failed: " (pr-str form#) sep# (map (fn [[k# v#]] (when (some #{k#} (flatten form#)) (str "\t" k# " : " v# sep#))) ~bindings)))))))))) |
| Comment by Jeff Weiss [ 27/May/11 8:16 AM ] |
|
A slight improvement I made in my own version of this code: flatten does not affect set literals. So if you do (assert (some #{x} [a b c d])) the value of x will not be printed. Here's a modified flatten that does the job: (defn symbols [sexp] "Returns just the symbols from the expression, including those inside literals (sets, maps, lists, vectors)." (distinct (filter symbol? (tree-seq coll? seq sexp)))) |
| Comment by Andy Fingerhut [ 18/Nov/12 1:06 AM ] |
|
Attaching git format patch clj-415-assert-prints-locals-v1.txt of Stuart Halloway's version of this idea. I'm not advocating it over the other variations, just getting a file attached to the JIRA ticket. |
[CLJ-373] update-in with empty key paths Created: 04/Jun/10 Updated: 08/Sep/12 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Enhancement | Priority: | Minor |
| Reporter: | Assembla Importer | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 1 |
| Labels: | None | ||
| Attachments: |
|
| Patch: | Code and Test |
| Approval: | Incomplete |
| Waiting On: | Chouser |
| Description |
|
To the topic of get-in and update-in. While I realize this is not a bug it is odd and in my eyes unexpected and unwanted behavior. get-in called with an empty path returns the hashmap it was given to walk through - this is as I expect and makes a lot of sense when dynamically (with generated pathes ) walking a hash map. update-in behaves differently and while from the implementation side, it's behavior too makes sense, it does not work as expected (at least not for me) update-in with an empty map creates a new key 'nil' so: (update-in {...} [] f) ist he same as (update-in {...} [nil] f) while (get-in {...} []) is not the same as (get-in {...} [nil]) and of cause differs from what update-in does. For automatically walking trees the behavior of get-in makes a lot more sense since the current behavior of update-in forces you to check for empty paths and if they are empty fall back to plain assoc and get (or get-in since this works): (if-let [r (butlast @path)] (do (alter m update-in r dissoc (last @path)) (alter m update-in r assoc {:name @sr} c)) (do (alter m dissoc (last @path)) (alter m assoc {:name @sr} c))) Next argument is that update-in with an empty map working on nil isn't easy to gasp, one needs to know the implementation details to realize that it works, I think 90% of the people reading update-in with [] will not instinctively know that it works on the key nil, so changing this would most likely not break any current code, and if it would the code would be bad anyway Chouser has, a very nice solution on the mailing list that would fix the problem I'm not sure if I'm entitled to post it here since I did not wrote it but it can be found in this thread: http://groups.google.com/group/clojure/browse_thread/thread/de5b20b8c3fe498b?hl=en Regards, |
| Comments |
| Comment by Assembla Importer [ 08/Oct/10 10:33 AM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/373 |
| Comment by Chouser [ 13/Nov/10 6:37 PM ] |
|
I've attached my code from the g.group thread in the form of a patch, in case it's sufficient. (Thanks to abedra for the gentle kick in the pants.) |
| Comment by Stuart Halloway [ 29/Nov/10 8:20 AM ] |
|
Looks to me like the patch is misusing if-let, e.g. (when-let [[k & mk] []] "Doh!")
=> Doh!
Please correct, and add tests for nil and [] keys (at least). |
| Comment by Scott Lowe [ 08/May/12 12:20 PM ] |
|
I will write some tests and correct this. |
| Comment by Scott Lowe [ 09/May/12 8:39 PM ] |
|
I'm sorry to report that my good intentions of wanting to help clear some of the project backlog has created more work by way of further questions. I'd also like to clarify the desired new behaviours for the test cases. Heinz proposed that an empty key sequence will not create a new nil key in the returned map.
(update-in {1 2} [] (constantly {2 3}))
{nil {2 3}, 1 2}
(update-in* {1 2} [] (constantly {2 3}))
{2 3}
(update-in {1 2} [] assoc 1 3)
{nil {1 3}, 1 2}
(update-in* {1 2} [] assoc 1 3)
{1 3}
Chouser also added that nil keys should be honoured, as before:
(update-in* {nil 2} [nil] (constantly 3))
{nil 3}
I've added a variety of tests to cover the existing behaviour and would like to confirm that the above is all that's required for new behaviour. The patch from November 2010 didn't work, but I tweaked it with a when-let as Stuart suggested and placed a check for an empty sequence of keys before the when-let block; because essentially, the primary behaviour change boils down to simply handling an empty sequence of keys, in addition to the existing behaviours. I'm not entirely convinced that these changes are a good thing, but at least there's now something concrete for discussion. Please have a look at what is there. The good news is that at least there are some tests covering update-in now. |
| Comment by Andy Fingerhut [ 24/May/12 10:35 PM ] |
|
clj-373-alter-behavior-of-update-in-with-empty-key-patch2.txt dated May 24, 2012 supersedes patch 0001-CLJ-373 |
| Comment by Fogus [ 15/Aug/12 11:21 AM ] |
|
This patch creates a new error mode highlighted by the following: (update-in {:a 1} [] inc)
; ClassCastException clojure.lang.PersistentArrayMap cannot be cast to java.lang.Number
The reason is that the code that executes in the event that the keys are empty (or nil) blindly assumes that the function given can be applied to the map itself. This is no problem in the case of assoc and the like, but clearly not for inc and many other useful functions. The old behavior was to throw an NPE and if any code relies on that fact is now broken. Maybe this is not a problem, but I'm kicking it back to get a little more discussion and to request that whatever the ultimate fix happens to be, its behavioral changes and error modes are noted in the docstring for update-in. |
| Comment by Gunnar Völkel [ 08/Sep/12 6:11 AM ] |
|
I vote for changing `update-in` to support empty key vectors. Because I think "(apply f m args)" in case of an empty vector is the natural continuation of the usual behavior of update-in:
Otherwise, you will always have to wrap update-in in something like the following when the keys vector is computed:
To Fogus' last post: (update-in {:a {:b 1}} [:a] inc) fails similar and is not handled with a special exception. |
[CLJ-346] (pprint-newline :fill) is not handled correctly Created: 12/May/10 Updated: 29/Nov/10 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | Backlog |
| Type: | Defect | Priority: | Minor |
| Reporter: | Assembla Importer | Assignee: | Tom Faulhaber |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Approval: | Incomplete |
| Waiting On: | Tom Faulhaber |
| Description |
|
Filled pretty printing (where we try to fit as many elements on a line as possible) is being too aggressive as we can see when we try to print the following array: user> (binding [*print-right-margin* 20] (pprint (int-array (range 10)))) Produces: [0, Rather than [0, 1, 2, 3, 4, or something like that. (I haven't worked through the exact correct representation for this case). We currently only use :fill style newlines for native java arrays. |
| Comments |
| Comment by Assembla Importer [ 24/Aug/10 8:01 AM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/346 |
| Comment by Assembla Importer [ 24/Aug/10 8:01 AM ] |
|
stu said: [file:diLxv6y4Sr35GVeJe5cbLr] |
| Comment by Assembla Importer [ 24/Aug/10 8:01 AM ] |
|
stu said: The second patch includes the first, and adds another test. |
| Comment by Assembla Importer [ 24/Aug/10 8:01 AM ] |
|
tomfaulhaber said: This patch was attached to the wrong bug. It should be attached to bug #347. There is no fix for this bug yet. |
| Comment by Rich Hickey [ 05/Nov/10 8:07 AM ] |
|
Is this current? |
| Comment by Stuart Halloway [ 29/Nov/10 8:48 PM ] |
|
Tom, this patch doesn't apply, and I am not sure why. Can you take a look? |
[CLJ-322] Enhance AOT compilation process to emit classfiles only for explicitly-specified namespaces Created: 29/Apr/10 Updated: 24/May/13 |
|
| Status: | In Progress |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | Release 1.6 |
| Type: | Enhancement | Priority: | Major |
| Reporter: | Chas Emerick | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 12 |
| Labels: | None | ||
| Attachments: |
|
| Patch: | Code and Test |
| Approval: | Incomplete |
| Waiting On: | Chas Emerick |
| Description |
|
Summary: still needs decision on implementation approach. This was originally/erroneously reported by Howard Lewis Ship in the clojure-contrib assembla: My build file specifies the namespaces to AOT compile but if I include another namespace (even from a JAR dependency) that is not AOT compiled, the other namespace will be compiled as well. In my case, I was using clojure-contrib's clojure.contrib.str-utils2 namespace, and I got a bunch of clojure/contrib/str_utils2 classes in my output directory. I think that the AOT compiler should NOT precompile any namespaces that are transitively reached, only namespaces in the set specified by the command line are appropriate. As currently coded, you will frequently find unwanted third-party dependencies in your output JARs; further, if multiple parties depend on the same JARs, this could cause bloating and duplication in the eventual runtime classpath. Having the option of shipping either all AOT-compiled classfiles or mixed source/AOT depending upon one's distribution requirements would make that phase of work with a clojure codebase significantly easier and less error-prone. The only question in my mind is what the default should be. We're all used to the current behaviour, but I'd guess that any nontrivial project where the form of the distributable matters (i.e. the source/AOT mix), providing as much control as possible by default makes the most sense. Given the tooling that most people are using, it's trivial (and common practice, IIUC) to provide a comprehensive list of namespaces one wishes to compile, so making that the default shouldn't be a hurdle to anyone. If an escape hatch is desired, a --transitive switch to clojure.lang.Compile could be added. |
| Comments |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/322 |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
hlship said: I'd like to reinforce this. I've been doing research on Clojure build tools for an upcoming talk and all of them (Maven, Leiningen, Gradle) have the same problem: the AOT compile extends from the desired namespaces (such as one containing a :gen-class) to every reached namespace. This is going to cause a real ugliness when application A uses libraries B and C that both depend on library D (such as clojure-contrib) and B and C are thus both bloated with duplicate, unwanted AOT compiled classes from the library D. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
cemerick said: This behaviour is an implementation detail of Clojure's AOT compilation process, and is orthogonal to any particular build tooling. I am working on a patch that would provide a mechanism for such tooling to disable this default behaviour. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
cemerick said: A first cut of a change to address this issue is here (caution, work in progress!): http://github.com/cemerick/clojure/commit/6f14e0790c0d283a7e44056adf1bb3f36bb16e0e This makes available a new recognized system property, clojure.compiler.transitive, which defaults to true. When set/bound to false (i.e. -Dclojure.compiler.transitive=false when using clojure.lang.Compile), only the first loaded file (either the ns named in the call to compile or each of the namespaces named as arguments to clojure.lang.Compile) will have classfiles written to disk. This means that this compilation invocation: java -cp <your classpath> -Dclojure.compiler.transitive=false clojure.lang.Compile com.bar com.baz
will generate classfiles only for com.bar and com.baz, but not for any of the namespaces or other files they load, require, or use. The only shortcoming of this WIP patch is that classfiles are still generated for proxy and gen-class classes defined outside of the explicitly-named namespaces. What I thought was a solution for this ended up breaking the loading of generated interfaces (as produced by defprotocol, etc). I'll take a second look at this before the end of the week, but wanted to get this out there so as to get any comments people might have. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
technomancy said: Looks good, but I'm having trouble getting it to work. I tried compiling from master of Chas's fork on github, but I still got the all the .class files generated with -Dclojure.compiler.transitive=false. It could be a quirk of the way I'm using ant to fork off processes though. Is it possible to set it using System/setProperty, or must it be given as a property on the command-line? |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
cemerick said: Bah, that's just bad documentation. :-/ The system property is only provided by clojure.lang.Compile; the value of it drives the binding of clojure.core/transitive-compile, which has a root binding of true. You should be able to configure the transitivity the same way you configure compile-path (system prop to clojure.lang.Compile or a direct binding when at the REPL, etc). If not, ping me in irc or elsewhere. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
meikelbrandmeyer said: I think, excluding parts 'load'ed is a little strong. I have some namespaces which load several parts from different files, but which belong to the same namespace. The most prominent example of such a case is clojure.core itself. I'm find with stopping require and use, but load is a bit too much, I'd say. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
technomancy said: Chas: Thanks; will give that a go. Meikel: Do people actually use load outside of clojure.core? I thought it was only used there because clojure.core is a "special" namespace where you want more vars to be available than can reasonably fit in a single file. Splitting up a namespace into several files is quite unadvisable otherwise. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
technomancy said: I can confirm that this works for me modulo the proxy/gen-class issue that Chas mentioned. I would love to see this in Clojure 1.2; it would really clean up a lot of build-related issues. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
meikelbrandmeyer said: I used it several times and this is the first time, I hear that it is unadvisable to do so. Even with a lower number of Vars in the namespace (c.c is here certainly exceptional) and might be of use to split several "sections" of code which belong to the same namespace but have different functionality. Whether to use a big comment in the source to indicate the section or split things into subfiles is a matter of taste. But it's a perfectly reasonable thing todo. Another use case, where I use this (and c.c.lazy-xml, IIRC) is to conditionally load code depending on whether a dependency is available or not. Eg. vimclojure uses c.c.pprint and c.c.stacktrace/clj-stacktrace transparently depending on their availability. There are perfectly legal uses of load. I don't see any "unadvisable" here. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
cemerick said: Thanks, Meikel; I had forgotten about that use case, as I don't use load directly myself at all. I probably wouldn't say it's inadvisable, just mostly unnecessary. In any case, that's a good catch. It complicates things a bit, but we'll see what happens. I'm going to take another whack at resolving the proxy/gen-class case and narrowing the impact of nontransitivity to use and require later tonight. I agree wholeheartedly that this should be in 1.2, assuming the technical bits work out. This has been an irritant for quite a long time. I actually believe that nontransitivity should be the default – no one wants or expects to have classfiles show up for dependencies show up when a project is AOT-compiled. I think the only negative impact would be whoever still fiddles with compilation at the REPL, and doesn't use maven or lein – and even then, it's just a matter of binding another var. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
meikelbrandmeyer said: Then the var should be added to the default bindings in the clojure.main repl. Then it's set!-able like the other vars ��� warn-on-reflection and friends. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
cemerick said: This is looking pretty good (still WIP): http://github.com/cemerick/clojure/commit/fedfb022ecef420a932b3d69c182ec7a8e5960a6 Thank you again for mentioning load, Meikel: it was very helpful in resolving the proxy/gen-class issue as well. Just a single data point: the jar produced by the medium-sized project I've been using for testing the changes has shrunk from 1.8MB to less than 1MB. That's not the only reason this is a good change, but it's certainly a nice side-effect. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
cemerick said: [file:aIWFiWHeGr35ImeJe5cbLA] |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
cemerick said: [file:aI7Eu-HeGr35ImeJe5cbLA] |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
cemerick said: Patched attached. The The user impact of changing the default would be:
|
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
hlship said: Just had a brain-storm: How about an option to support transitive compilation, but only if the Clojure source file being compiled as a file: URL (i.e., its a local file on the file system, not a file stored in a JAR). That would make it easier to use compilation on the local project without transitively compiling imported libraries, such as clojure-contrib. So transitive-compile should be a keyword, not a boolean, with values :all (for 1.1 behavior), :none (to compile only the exact specified namespaces) or :local (to compile transitively, but only for local files, not source files from JARs). |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
cemerick said: (Crossposted to the clojure-dev list) I thought about this some, and I don't think that's a good idea, at least for now. I'm uncomfortable with semantics changing depending upon where code is being loaded from – which, depending upon a tool's implementation, might be undefined. E.g. if the com.foo.bar ns is available in source form in one directory, but as classes from a jar, and classpaths aren't being constructed in a stable fashion, then the results of compilation will change. If we decide that special treatment depending upon the source of code is warranted in the future, that's a fairly straightforward thing to do w.r.t. the API – we could have :all and :local as you suggest, with nil representing :none. |
| Comment by Assembla Importer [ 28/Sep/10 12:18 AM ] |
|
stu said: Rich is not comfortable enough with the implementation complexity of this patch (e.g. the guard clause for proxies and gen-class) to slide this in as a minor fix under the wire for 1.2. Better to live with the pain we know a little longer than ship something we don't have enough experience with to be confident. |
| Comment by Chas Emerick [ 19/Nov/10 9:28 PM ] |
|
Updated patch to cleanly apply to HEAD and address issues raised by screening done by Cosmin Stejerean. Also includes proper tests. Note: this patch's tests require the fix for |
| Comment by Stuart Halloway [ 29/Nov/10 7:18 AM ] |
|
the "-resolved" patch resolves a conflict in main.clj |
| Comment by Stuart Halloway [ 29/Nov/10 7:25 AM ] |
|
Several questions:
|
| Comment by Stuart Sierra [ 10/Dec/10 3:34 PM ] |
|
An alternative approach: patch write-classes-1.diff.gz From my forked branch What this patch does:
This approach was prompted by the following observations:
|
| Comment by Chas Emerick [ 10/Dec/10 4:04 PM ] |
|
S. Halloway: My apologies, I didn't know you had commented. I thought that, having assigned this issue to myself, I'd be notified of updates. FWIW, I aim to review your comments and SS' approach over the weekend. |
| Comment by Chas Emerick [ 16/Dec/10 7:36 AM ] |
|
S. Halloway: 1. Certainly shouldn't happen. AFAIK, others have screened the patch, presumably with a successful build. |
| Comment by Chas Emerick [ 16/Dec/10 9:00 AM ] |
|
I think S. Sierra's approach is fundamentally superior what I offered. I have two suggestions: one slight perspective change (which implies no change in the actual implementation), and an idea for an even simpler approach (at least from a user perspective), in that order. While interop is the driving requirement behind AOT, I absolutely do not want to have to keep an updated enumeration of all of the classes resulting from each and every defrecord et al. usages in my pom.xml/project.clj (and I wouldn't wish the task of ferreting those usages and their resulting classnames on any build tool author). Right now, *compile-write-classes* is documented to be a set of classname strings, but could just as easily be any other function. *compile-write-classes* should be documented to accept any predicate function (renamed to e.g. *compile-write-class?*?). There's no reason why it shouldn't be bound to, e.g. #(re-matches #"foo\.bar\.[\w_]+$" %) if I know that all my records are defined in the foo.bar namespace. To go along with that, I think some package/classname-globbing utilities along with corresponding options to clojure.lang.Compile would be most welcome. Classname munging rules are not exactly obvious, and it'd be good to make things a little easier for users in this regard. Another alternativeIf there's a closed set of forms that generate classes that one might reasonably be interested in having in a build result (outside of use cases for pervasive AOT), then why not have a simple option that only those forms utilize? gen-class and gen-interface already do this, but reusing the all-or-nothing *compile-files* binding; if they keyed off of a binding that implied a diminished scope (e.g. *compile-interop-forms* – which would be true if *compile-files* were true), then they'd do exactly what we wanted. Extending this approach to deftype (and therefore defrecord) should be straightforward. An implementation of this would probably be somewhat more complicated than S. Sierra's patch, though not as complex as my original stab at the problem (i.e. no *load-level*). On the plus side: 1. No additional configuration for users or implementation work for build tool authors, aside from the addition of the boolean diminished-scope AOT option I can see wanting to further restrict AOT to specific classnames in certain circumstances, in which case the above and S. Sierra's patch might be complimentary. |
| Comment by Stuart Sierra [ 16/Dec/10 11:49 AM ] |
|
I like the idea of *compile-interop-forms*. But is it always possible to determine what an "interop form" is? I think it is, I'm just not sure. |
| Comment by Allen Rohner [ 09/Oct/11 12:50 PM ] |
|
I'm also in favor of compile-interop-forms. As far as determining, how about sticking metadata on the var? (defmacro ^{:interop-form true} deftype ...) |
| Comment by Stuart Sierra [ 21/Oct/11 8:38 AM ] |
|
Summary and design discussion on wiki at http://dev.clojure.org/display/design/Transitive+AOT+Compilation |
| Comment by Stuart Sierra [ 29/Nov/11 6:54 PM ] |
|
New attachment compile-interop-1.patch has new approach: Add a third possible value for *compile-files*. True and false keep their original meanings, but :interop causes only interop-related forms to be written out as .class files. "Interop forms" are gen-class, gen-interface, deftype, defrecord, defprotocol, and definterface. Pros:
Cons:
|
| Comment by Stuart Sierra [ 02/Dec/11 8:12 AM ] |
|
Just realized my patch doesn't solve the transitive compilation problem. If library A loads library B, then compiling interop forms in A will also emit interop .class files in B. |
| Comment by Paudi Moriarty [ 01/Jan/13 3:55 AM ] |
|
It's disappointing to see an important issue like this still unresolved after 2.5 years. This is a real pain for us. We have a large closed source project where shipping source is not an option. This forces us to manage the AOT'ing of dependencies due to the hard dependency on protocol interfaces introduced by transitive AOT compilation (see https://groups.google.com/forum/?fromgroups=#!topic/clojure-dev/r3A1JOIiwVU). |
| Comment by Andy Fingerhut [ 01/Jan/13 4:27 PM ] |
|
Paul, do you have a suggestion for which of the approaches described in comments here, or on the wiki page http://dev.clojure.org/display/design/Transitive+AOT+Compilation would be preferable solution for you? Or perhaps even a patch that implements your preferred approach? |
| Comment by Howard Lewis Ship [ 04/Jan/13 4:18 PM ] |
|
Andy, I'm now consulting with Paudi's organization, so I think I can speak for him (I'm now the default buildmeister). I like Stuart's :interop idea, but that is somewhat orthogonal to our needs. I return to what I would like; compilation would compile specific namespaces; dependencies of those namespaces would not be compiled. To be honest, I'm still a little hung up on the interop forms: especially defprotocol and friends; from a cursory glance, it appears that todays AOT compilation will compile the protocol into a Java class, then compile the namespace that references the protocol with the assumption that the protocol's Java class is available. When we use build rules to only package our namespace's class files into the output JAR, the code fails with a NoClassDefFoundError because the protocol really needs to be recompiled, at runtime compilation, into an in-memory Java class. Obviously, supporting this correctly will be a challenge; the compiled bytecode for our namespace would ideally: I can imagine any number of ways to juggle things to make this work, so I won't suggest a specific implementation. In the meantime, our workaround is to create a "stub" module as part of our build; it simply requires in the necessary namespaces (for example, org.clojure:core.cache); this forces an AOT compile of the dependencies and we have a special rule to package such dependencies in the stub module's output JAR. This may not be a scalable problem, and it is expensive to identify what 3rd party dependencies require this treatment. |
| Comment by Stuart Halloway [ 24/May/13 1:25 PM ] |
|
I am marking this incomplete because there does not yet seem to be plurality, much less consensus or unanimity, on approach. Personally I am in favor of a solution based on a predicate that gets handed the class name and compiled bits, and then can choose whether to write the class. Pretty close to Stuart Sierra's compile-write-classes. Might be possible to flow more information than classname to the predicate. |
[CLJ-291] (take-nth 0 coll) redux... Created: 08/Apr/10 Updated: 10/Dec/10 |
|
| Status: | In Progress |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | Approved Backlog |
| Type: | Enhancement | Priority: | Minor |
| Reporter: | Assembla Importer | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Approval: | Incomplete |
| Description |
|
I dont seem to be able make the old ticket uninvalid so here goes (let [j 0 I used jvisualvm and the jvm is doing some RNI call - no clojure code is running at all |
| Comments |
| Comment by Assembla Importer [ 17/Oct/10 9:47 AM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/291 |
| Comment by Assembla Importer [ 17/Oct/10 9:47 AM ] |
|
bhurt said: Before this bug gets marked as invalid as well, let me point out that the problem here is that (take-nth 0 any-list) is a meaningless construction- the only question is what to do when this happens. IMHO, the correct behavior is to throw an exception. |
| Comment by Assembla Importer [ 17/Oct/10 9:47 AM ] |
|
ataggart said: [file:dfNhoS2Cir3543eJe5cbLA]: throws IllegalArgumentException on negative step size |
| Comment by Stuart Halloway [ 29/Oct/10 10:36 AM ] |
|
Does calling (take-nth 0 ...) cause the problem, or only realizing the result? |
| Comment by Chouser [ 29/Oct/10 11:06 AM ] |
|
I'm not seeing a problem. Calling take-nth and even partially consuming the seq it returns works fine for me: (take 5 (take-nth 0 [1 2 3])) Note however that it is returning an infinite lazy seq. The example in the issue description seems to include essentially (doall <infinite-lazy-seq>) which does blow the heap: (doall (range)) This issue still strikes me as invalid. |
| Comment by Rich Hickey [ 29/Oct/10 11:06 AM ] |
|
(take-nth 0 ...) returns an infinite sequence of the first item: (take 12 (take-nth 0 [1 2 3])) Is something other than this happening on Solaris? |
[CLJ-250] debug builds Created: 27/Jan/10 Updated: 14/Mar/13 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | Release 1.2 |
| Fix Version/s: | Approved Backlog |
| Type: | Enhancement | Priority: | Minor |
| Reporter: | Stuart Halloway | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Approval: | Incomplete |
| Waiting On: | Rich Hickey |
| Description |
|
This ticket includes two patches:
Things to consider before approving these patches:
|
| Comments |
| Comment by Assembla Importer [ 24/Aug/10 6:05 AM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/250 |
| Comment by Stuart Halloway [ 07/Dec/10 8:23 PM ] |
|
Ignore the old patches. Considering the following implementation, please review and then move ticket to waiting on Stu:
|
| Comment by Rich Hickey [ 08/Dec/10 11:00 AM ] |
|
#3 - root bound only #6 - my biggest reservation is that this isn't yet informed by maven best practices |
| Comment by Stuart Sierra [ 08/Dec/10 2:09 PM ] |
|
System properties can be passed through Maven, so I do not anticipate this being a problem. However, I would prefer *assert* to remain true by default. |
| Comment by Chas Emerick [ 09/Dec/10 7:19 AM ] |
|
SS is correct about this approach not posing any issue for Maven. In addition, the build could easily be set up to always emit two jars, one "normal", one "debug". I'd suggest that, while clojure.debug might have broad effect, additional properties should be available to provide fine-grained control over each of the additional "debug"-related parameterizations that might become available in the future. I'd like to raise a couple of potentially tangential concerns (after now thinking about assertions for a bit in the above context), some or all of which may simply be a result of my lack of understanding in various areas. Looking at where assert is used in core.clj (only two places AFAICT: validating arguments to derive and checking pre- and post-conditions in fn), it would seem unwise to make it false by default. i.e. non-Named values would be able to get into hierarchies, and pre- and post-conditions would simply be ignored. It's my understanding that assertions (talking here of the JVM construct, from which Clojure reuses AssertionError) should not be used to validate arguments to public API functions, or used to validate any aspect of a function's normal operation (i.e. "where not to use assertions"). That would imply that derive should throw IllegalArugmentException when necessary, and fn pre- and post-conditions should perhaps throw IllegalStateException – or, in any case, something other than AssertionError via assert. This would match up far better with most functions in core using assert-args rather than assert, the former throwing IllegalArgumentException rather than AssertionError. That leads me to the question: is assert (and *assert*) intended to be a Clojure construct, or a quasi-interop form? If the former, then it can roughly have whatever semantics we want, but then it seems like it should not be throwing AssertionError. If the latter, then AssertionError is appropriate on the JVM, but then we need to take care that assertions can be enabled and disabled at runtime (without having to switch around different builds of Clojure), ideally using the host-defined switches (e.g. -ea and friends) and likely not anything like *assert*. I don't know if this is possible or practical at this point (I presume this would require nontrivial compiler changes). Hopefully the above is not water under the bridge at this point. Thank you in advance for your forbearance. |
| Comment by Rich Hickey [ 09/Dec/10 8:08 AM ] |
|
Thanks for the useful input Chas. Nothing is concluded yet. I think we should step back and look at the objective here, before moving forward with a solution. Being a dynamic language, there are many things we might want to validate about our programs, where the cost of checking is something we are unwilling to pay in production. Being a macro, assert has the nice property that, should *assert* not be true during compilation, it generates nil, no conditional test at all. Thus right now it is more like static conditional compilation. Java assert does have runtime toggle-ability, via -ea as you say. I haven't looked at the bytecode generated for Java asserts, but it might be possible for Clojure assert to do something similar, if the runtime overhead is negligible. It is quite likely that HotSpot has special code for eliding the assertion bytecode given a single check of some flag. I'm just not sure that flag is Class.desiredAssertionStatus. Whether this turns into changes in assert or pre/post conditions, best practices etc is orthogonal and derived. Currently we don't have a facility to run without the checks. We need to choose between making them disappear during compilation (debug build) or runtime (track -ea) or both. Then we can look at how that is reflected in assert/pre-post and re-examine existing use of both. The "where not to use assertions" doc deals with them categorically, but in not considering their cost, seems unrealistic IMO. I'd appreciate it if someone could look into how assert is generated and optimized by Java itself. |
| Comment by Chas Emerick [ 09/Dec/10 5:04 PM ] |
|
Bytecode issues continue to be above my pay grade, unfortunately… A few additional thoughts in response that you may or may not be juggling already: assert being a macro makes total sense for what it's doing. Trouble is, "compile-time" is a tricky concept in Clojure: there's code-loading-time, AOT-compile-time, and transitively-AOT-compile-time. Given that, it's entirely possible for an application deployed to a production environment that contains a patchwork of code or no code produced by assert usages in various libraries and namespaces depending upon when those libs and ns' were loaded, AOT-compiled, or their dependents AOT-compiled, and the value of *assert* at each of those times. Of course, this is the case for all such macros whose results are dependent upon context-dependent state (I think this was a big issue with clojure.contrib.logging, making it only usable with log4j for a while). What's really attractive about the JVM assertion mechanism is that it can be parameterized for a given runtime on a per-package basis, if desired. Reimplementing that concept so that assert can be *ns*-sensitive seems like it'd be straightforward, but the compile-time complexity already mentioned remains, and the idea of having two independently-controlled assertion facilities doesn't sound fun. I know nearly nothing about the CLR, but it would appear that it doesn't provide for anything like runtime-controllable assertions. |
| Comment by Stuart Halloway [ 29/Dec/10 3:17 PM ] |
|
The best (dated) evidence I could find says that the compiler sets a special class static final field $assertionsDisabled based on the return of desiredAssertionStatus. HotSpot doesn't do anything special with this, dead code elimination simply makes it go away. The code indeed compiles this way: 11: getstatic #6; //Field $assertionsDisabled:Z Even if we were 100% sure that assertion removal was total, I would still vote for a separate Clojure-level switch, for the following reasons:
Rich: awaiting your blessing to move forward on this. |
| Comment by Rich Hickey [ 07/Jan/11 9:42 AM ] |
|
The compiler sets $assertionsDisabled when, in static init code? Is there special support in the classloader for it? Is there a link to the best dated evidence you found? |
| Comment by Stuart Halloway [ 07/Jan/11 9:51 AM ] |
|
| Comment by Stuart Halloway [ 07/Jan/11 9:57 AM ] |
|
Link: Google "java assert shirazi". (Not posting link because I can't tell in 10 secs whether it includes my session information.) |
| Comment by Alexander Kiel [ 14/Mar/13 1:28 PM ] |
|
Is there anything new on this issue? I also look for a convenient way to disable assertions in production. |
[CLJ-211] Support arbitrary functional destructuring via -> and ->> Created: 17/Nov/09 Updated: 10/Dec/10 |
|
| Status: | In Progress |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | Approved Backlog |
| Type: | Enhancement | Priority: | Minor |
| Reporter: | Assembla Importer | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Approval: | Incomplete |
| Description |
|
Support arbitrary functional destructuring, that is the use of The discussion began here: The attached patch implements the spec described here: That is, the following examples would now work: user=> (let [(-> str a) 1] a) user=> (let [[a (-> str b) c] [1 2]] (list a b c)) user=> (let [(->> (map int) [a b]) "ab"] (list a b)) |
| Comments |
| Comment by Assembla Importer [ 28/Sep/10 6:57 AM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/211 |
| Comment by Assembla Importer [ 28/Sep/10 6:57 AM ] |
|
chouser@n01se.net said: [file:aHWQ_W06Kr3O89eJe5afGb]: [PATCH] Support -> and ->> in destructuring forms. |
| Comment by Assembla Importer [ 28/Sep/10 6:57 AM ] |
|
cgrand said: I think the current patch suffers from the problem described here http://groups.google.com/group/clojure-dev/msg/80ba7fad2ff04708 too. |
| Comment by Assembla Importer [ 28/Sep/10 6:57 AM ] |
|
richhickey said: so, don't use syntax-quote, just use clojure.core/-> |
| Comment by Assembla Importer [ 28/Sep/10 6:57 AM ] |
|
chouser@n01se.net said: Only -> and ->> are actually legal here anyway – if you've locally bound foo to -> there's not really any good reason to think (fn [(foo inc a)] a) should work. And if you've redefined -> or ->> to mean something else in your ns, do we need to catch that at compile time, or is it okay to emit the rearranged code and see what happens? In short, would '#{ |
| Comment by Assembla Importer [ 28/Sep/10 6:57 AM ] |
|
cgrand said: Only -> and ->> are legal here but what if they are aliased or shadowed? Instead of testing the symboil per se I would check, if:
(when-not (&env (first b)) (#{#'clojure.core/-> #'clojure.core/->>} (resolve (first b))))
but it requires to change destructure's sig to pass the env around |
| Comment by Stuart Halloway [ 03/Dec/10 1:03 PM ] |
|
Rich: Are you assigned to this by accident? If so, please deassign yourself. |
[CLJ-84] GC Issue 81: compile gen-class fail when class returns self Created: 17/Jun/09 Updated: 10/Dec/10 |
|
| Status: | In Progress |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | Approved Backlog |
| Fix Version/s: | Approved Backlog |
| Type: | Defect | Priority: | Minor |
| Reporter: | Assembla Importer | Assignee: | Rich Hickey |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Approval: | Incomplete |
| Waiting On: | Chouser |
| Description |
Reported by davidhaub, Feb 14, 2009 When attempting to compile the following program, clojure fails with a ClassNotFoundException. It occurs because one of the methods returns the same class that is being generated. If the returnMe method below is changed to return an Object, the compile succeeds. Beware when testing! If the classpath contains a class file (say from a prior successful build when the returnMe method was changed to return an object), the compile will succeed. Always clear out the clojure.compile.path prior to compiling. ;badgenclass.clj (ns badgenclass (:gen-class :state state :methods [[returnMe [] badgenclass]] :init init)) (defn -init [] [[] nil]) (defn -returnMe [this] this) #!/bin/sh rm -rf classes mkdir classes java -cp lib/clojure.jar:classes:. -Dclojure.compile.path=classes \ clojure.lang.Compile badgenclass Comment 1 by chouser, Mar 07, 2009 Attached is a patch that accepts strings or symbols for parameter and return class names, and generates the appropriate bytecode without calling Class/forName. It fixes this issue, but because 'ns' doesn't resolve :gen-class's arguments, class names aren't checked as early anymore. :gen-class-created classes with invalid parameter or return types can even be instantiated, and no error will be reported until the broken method is called. One possible alternative would be to call Class/forName on any symbols given, but allow strings to use the method given by this patch. To return your own type, you'd need a method defined like: [returnMe [] "badgenclass"] Any thoughts? |
| Comments |
| Comment by Assembla Importer [ 28/Sep/10 5:09 PM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/84 |
| Comment by Assembla Importer [ 28/Sep/10 5:09 PM ] |
|
oranenj said: [file:cWS6Aww30r3RbzeJe5afGb]: on comment 1 |
| Comment by Assembla Importer [ 28/Sep/10 5:09 PM ] |
|
richhickey said: Updating tickets (#8, #19, #30, #31, #126, #17, #42, #47, #50, #61, #64, #69, #71, #77, #79, #84, #87, #89, #96, #99, #103, #107, #112, #113, #114, #115, #118, #119, #121, #122, #124) |
| Comment by Stuart Halloway [ 30/Oct/10 11:58 AM ] |
|
The approach take in the initial patch (delaying resolution of symbols into classes) is fine: gen-class makes no promise about when this happens, and the dynamic approach feels more consistent with Clojure. I think the proposed (but not implemented) use of string/symbol to control when class names are resolved is a bad idea: magical and not implied by the types. Needed:
|
| Comment by Chouser [ 30/Oct/10 9:29 PM ] |
|
Wow, 18-month-old patch, back to haunt me for Halloway'een So what does it mean that the assignee is Rich, but it's waiting on me? |
| Comment by Stuart Halloway [ 01/Nov/10 9:17 AM ] |
|
I am using Approval = Incomplete plus Waiting On = Someone to let submitters know that there is feedback waiting, and that they can move the ticket forward by acting on it. The distinction is opportunity to contribute (something has been provided to let you move forward) vs. expectation of contribution. |
[CLJ-69] GC Issue 66: Add "keyset" to Clojure; make .keySet for APersistentMap return IPersistentSet Created: 17/Jun/09 Updated: 10/Dec/10 |
|
| Status: | In Progress |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | Approved Backlog |
| Fix Version/s: | Approved Backlog |
| Type: | Enhancement | Priority: | Minor |
| Reporter: | Assembla Importer | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Approval: | Incomplete |
| Description |
Reported by wolfe.a.jason, Feb 04, 2009 Describe the feature/change. Add "keyset" to Clojure; make .keySet for APersistentMap return an IPersistentSet Was this discussed on the group? If so, please provide a link to the discussion: http://groups.google.com/group/clojure/browse_thread/thread/66e708e477ae992f/ff3d8d588068b60e?hl=en#ff3d8d588068b60e ----------------------------------------------------- A patch is attached. Some notes: I chose to add a "keyset" function, rather than change the existing "keys", so as to avoid breaking anything. The corresponding RT.keyset function just calls .keySet on the argument. I would have liked to have "keyset" return an IPersistentSet even when passed a (non-Clojure) java.util.Map, but this seems impossible to do in sublinear time because of essentially the same limitation mentioned in the above thread (the Map interface does not support getKey() or entryAt()) -- assuming, again, that "get" is supposed to return the actual (identical?) key in a set, and not just an .equal key. I then changed the implementation of .keySet for APersistentMap to essentially copy APersistentSet. A more concise alternative would have been to extend APersistentSet and override the .get method, but that made me a bit nervous (since if APeristentSet changed this could break). Anyway, this is my first patch for the Java side of Clojure, and I'm not yet solid on the conventions and aesthetics, so comments/questions/criticisms/requests for revisions are very welcome. |
| Comments |
| Comment by Assembla Importer [ 28/Sep/10 7:00 AM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/69 |
| Comment by Assembla Importer [ 28/Sep/10 7:00 AM ] |
|
oranenj said: [file:dKgE6mw3Gr3O2PeJe5afGb] |
| Comment by Assembla Importer [ 28/Sep/10 7:00 AM ] |
|
richhickey said: Updating tickets (#8, #19, #30, #31, #126, #17, #42, #47, #50, #61, #64, #69, #71, #77, #79, #84, #87, #89, #96, #99, #103, #107, #112, #113, #114, #115, #118, #119, #121, #122, #124) |
| Comment by Stuart Halloway [ 03/Dec/10 1:12 PM ] |
|
patch not in correct format |
[CLJ-5] Unintuitive error response in clojure 1.0 Created: 17/Jun/09 Updated: 28/Apr/12 |
|
| Status: | Open |
| Project: | Clojure |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | Backlog |
| Type: | Enhancement | Priority: | Minor |
| Reporter: | Assembla Importer | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Attachments: |
|
| Patch: | Code and Test |
| Approval: | Incomplete |
| Description |
|
The following broken code: (let [[x y] {}] x) provides the following stack trace: Exception in thread "main" java.lang.UnsupportedOperationException: nth not supported on this type: PersistentArrayMap (test.clj:0) The message "nth not supported on this type" while correct doesn't make the cause of the error very clear. Better error messages when destructuring would be very helpful. |
| Comments |
| Comment by Assembla Importer [ 24/Aug/10 10:44 AM ] |
|
Converted from http://www.assembla.com/spaces/clojure/tickets/5 |
| Comment by Eugene Koontz [ 11/Nov/11 7:36 PM ] |
|
Please see the attached patch which produces a (hopefully more clear) error message as shown below (given the broken code shown in the original bug report): Clojure 1.4.0-master-SNAPSHOT
user=> (let [x 42 y 43] (+ x y))
85
user=> (let [[x y] {}] x)
UnsupportedOperationException left side of binding must be a symbol (found a PersistentVector instead). clojure.lang.Compiler.checkLet (Compiler.java:6545)
user=>
In addition, this patch checks the argument of (let) as shown below: user=> (let 42) UnsupportedOperationException argument to (let) must be a vector (found a Long instead). clojure.lang.Compiler.checkLet (Compiler.java:6553) |
| Comment by Eugene Koontz [ 11/Nov/11 7:38 PM ] |
|
Patch produced by doing git diff against commit ba930d95fc (master branch). |
| Comment by Eugene Koontz [ 13/Nov/11 11:24 PM ] |
|
Sorry, this patch is wrong: it assumes that the left side of the binding is wrong - the [x y] in : (let [[x y] {}] x)
because [x y] is a vector, when in fact, the left side is fine (per http://clojure.org/special_forms#let : "Clojure supports abstract structural binding, often called destructuring, in let binding lists".) So it's the right side (the {}) that needs to be checked and flagged as erroneous, not the [x y]. |
| Comment by Carin Meier [ 30/Nov/11 12:15 PM ] |
|
Add patch better-error-for-let-vector-map-binding This produces the following: (let [[x y] {}] x)
Exception map binding to vector is not supported
There are other cases that are not handled by this though — like binding vector to a set user=> (let [[x y] #{}] x)
UnsupportedOperationException nth not supported on this type: PersistentHashSet
Wondering if it might be better to try convert the map to a seq to support? Although this might be another issue. Thoughts? |
| Comment by Aaron Bedra [ 30/Nov/11 7:12 PM ] |
|
This seems too specific. Is this issue indicative of a larger problem that should be addressed? Even if this is the only case where bindings produce poor error messages, all the cases described above should be addressed in the patch. |
| Comment by Carin Meier [ 16/Dec/11 7:47 AM ] |
|
Unfortunately, realized that this still does not cover the nested destructuring cases. Coming to the conclusion, that my approach above is not going to work for this. |
| Comment by Carin Meier [ 28/Apr/12 10:46 PM ] |
|
File: clj-5-destructure-error.diff Added support for nested destructuring errors let [[[x1 y1][x2 y2]] [[1 2] {}]]
;=> UnsupportedOperationException let cannot destructure class clojure.lang.PersistentArrayMap.
|