Clojure

Hints don't work with #() form of function

Details

  • Type: Enhancement Enhancement
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: Release 1.7
  • Component/s: None
  • Labels:
  • Patch:
    Code and Test
  • Approval:
    Screened

Description

Example showing how a local fn can be hinted but an anonymous function cannot:

;; OK
user> (let [ex (java.util.concurrent.Executors/newFixedThreadPool 1)
            f (fn [])]
        (.submit ex ^Runnable f))
nil
;; ERROR - this should work the same as the previous
user> (let [ex (java.util.concurrent.Executors/newFixedThreadPool 1)]
        (.submit ex #()))
CompilerException java.lang.IllegalArgumentException: More than one matching method found: submit, compiling:(/private/var/folders/7r/_1fj0f517rgcxwx79mn79mfc0000gn/T/form-init7901279404687292754.clj:3:9)

Cause: Functions have metadata, but Compiler does not look in them for type hints. Var expressions and local bindings use :tag metadata to override return of getJavaClass(). Compiler parses #() into a FnExpr, which always return AFunction as its class.

Proposed: Change FnExpr.getJavaClass() to return tag as type if it is available.

Patch: clj-1378-v2.diff

Screened by: Alex Miller

  1. clj-1378.diff
    12/Mar/14 4:16 AM
    0.8 kB
    Jozef Wagner
  2. clj-1378-v2.diff
    12/Mar/14 2:51 PM
    2 kB
    Jozef Wagner

Activity

Alex Miller made changes -
Field Original Value New Value
Description ;; WORKS
(deftest test-add-job
  (let [pool (java.util.concurrent.Executors/newFixedThreadPool 10)
        counter 50000
        f (fn [])]
    (dotimes [i counter]
      (.submit pool ^Runnable f ))
    (Thread/sleep 1000)
    (is (= counter (count (all-jobs))))))

;; FAILS
(deftest test-add-job
  (let [pool (java.util.concurrent.Executors/newFixedThreadPool 10)
        counter 50000]
    (dotimes [i counter]
      (.submit pool ^Runnable #()))
    (Thread/sleep 1000)
    (is (= counter (count (all-jobs))))))

Caused by: java.lang.IllegalArgumentException: More than one matching method found: submit
at clojure.lang.Compiler.getMatchingParams(Compiler.java:2380)
at clojure.lang.Compiler$InstanceMethodExpr.<init>(Compiler.java:1412)
at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:952)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6560)
... 87 more
{code}
;; WORKS
(deftest test-add-job
  (let [pool (java.util.concurrent.Executors/newFixedThreadPool 10)
        counter 50000
        f (fn [])]
    (dotimes [i counter]
      (.submit pool ^Runnable f ))
    (Thread/sleep 1000)
    (is (= counter (count (all-jobs))))))

;; FAILS
(deftest test-add-job
  (let [pool (java.util.concurrent.Executors/newFixedThreadPool 10)
        counter 50000]
    (dotimes [i counter]
      (.submit pool ^Runnable #()))
    (Thread/sleep 1000)
    (is (= counter (count (all-jobs))))))

Caused by: java.lang.IllegalArgumentException: More than one matching method found: submit
at clojure.lang.Compiler.getMatchingParams(Compiler.java:2380)
at clojure.lang.Compiler$InstanceMethodExpr.<init>(Compiler.java:1412)
at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:952)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6560)
... 87 more
{code}
Jozef Wagner made changes -
Attachment clj-1378.diff [ 12869 ]
Alex Miller made changes -
Comment [ I suspect this is because functions don't have metadata. Metadata is attached to vars or locals (neither of which exist in the anonymous function case). So the issue is not really the anonymous function, but that there is no place to hang the meta. For example this example using #() is fine:

{code}
;; WORKS
(deftest test-add-job
(let [pool (java.util.concurrent.Executors/newFixedThreadPool 10)
counter 50000
f #()]
(dotimes [i counter]
(.submit pool ^Runnable f ))
(Thread/sleep 1000)
(is (= counter (count (all-jobs))))))
{code} ]
Alex Miller made changes -
Patch Code [ 10001 ]
Approval Triaged [ 10120 ]
Labels interop typehints
Issue Type Defect [ 1 ] Enhancement [ 4 ]
Jozef Wagner made changes -
Attachment clj-1378-v2.diff [ 12872 ]
Rich Hickey made changes -
Approval Triaged [ 10120 ] Vetted [ 10003 ]
Rich Hickey made changes -
Fix Version/s Release 1.7 [ 10250 ]
Alex Miller made changes -
Patch Code [ 10001 ] Code and Test [ 10002 ]
Description {code}
;; WORKS
(deftest test-add-job
  (let [pool (java.util.concurrent.Executors/newFixedThreadPool 10)
        counter 50000
        f (fn [])]
    (dotimes [i counter]
      (.submit pool ^Runnable f ))
    (Thread/sleep 1000)
    (is (= counter (count (all-jobs))))))

;; FAILS
(deftest test-add-job
  (let [pool (java.util.concurrent.Executors/newFixedThreadPool 10)
        counter 50000]
    (dotimes [i counter]
      (.submit pool ^Runnable #()))
    (Thread/sleep 1000)
    (is (= counter (count (all-jobs))))))

Caused by: java.lang.IllegalArgumentException: More than one matching method found: submit
at clojure.lang.Compiler.getMatchingParams(Compiler.java:2380)
at clojure.lang.Compiler$InstanceMethodExpr.<init>(Compiler.java:1412)
at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:952)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6560)
... 87 more
{code}
Example showing how a local fn can be hinted but an anonymous function cannot:

{code}
;; OK
user> (let [ex (java.util.concurrent.Executors/newFixedThreadPool 1)
            f (fn [])]
        (.submit ex ^Runnable f))
nil
;; ERROR - this should work the same as the previous
user> (let [ex (java.util.concurrent.Executors/newFixedThreadPool 1)]
        (.submit ex #()))
CompilerException java.lang.IllegalArgumentException: More than one matching method found: submit, compiling:(/private/var/folders/7r/_1fj0f517rgcxwx79mn79mfc0000gn/T/form-init7901279404687292754.clj:3:9)
{code}

*Cause:* Functions have metadata, but Compiler does not look in them for type hints. Var expressions and local bindings use :tag metadata to override return of getJavaClass(). Compiler parses #() into a FnExpr, which always return AFunction as its class.

*Proposed:* Change FnExpr.getJavaClass() to return tag as type if it is available.

*Patch:* clj-1378-v2.diff

*Screened by:*
Alex Miller made changes -
Approval Vetted [ 10003 ] Screened [ 10004 ]
Description Example showing how a local fn can be hinted but an anonymous function cannot:

{code}
;; OK
user> (let [ex (java.util.concurrent.Executors/newFixedThreadPool 1)
            f (fn [])]
        (.submit ex ^Runnable f))
nil
;; ERROR - this should work the same as the previous
user> (let [ex (java.util.concurrent.Executors/newFixedThreadPool 1)]
        (.submit ex #()))
CompilerException java.lang.IllegalArgumentException: More than one matching method found: submit, compiling:(/private/var/folders/7r/_1fj0f517rgcxwx79mn79mfc0000gn/T/form-init7901279404687292754.clj:3:9)
{code}

*Cause:* Functions have metadata, but Compiler does not look in them for type hints. Var expressions and local bindings use :tag metadata to override return of getJavaClass(). Compiler parses #() into a FnExpr, which always return AFunction as its class.

*Proposed:* Change FnExpr.getJavaClass() to return tag as type if it is available.

*Patch:* clj-1378-v2.diff

*Screened by:*
Example showing how a local fn can be hinted but an anonymous function cannot:

{code}
;; OK
user> (let [ex (java.util.concurrent.Executors/newFixedThreadPool 1)
            f (fn [])]
        (.submit ex ^Runnable f))
nil
;; ERROR - this should work the same as the previous
user> (let [ex (java.util.concurrent.Executors/newFixedThreadPool 1)]
        (.submit ex #()))
CompilerException java.lang.IllegalArgumentException: More than one matching method found: submit, compiling:(/private/var/folders/7r/_1fj0f517rgcxwx79mn79mfc0000gn/T/form-init7901279404687292754.clj:3:9)
{code}

*Cause:* Functions have metadata, but Compiler does not look in them for type hints. Var expressions and local bindings use :tag metadata to override return of getJavaClass(). Compiler parses #() into a FnExpr, which always return AFunction as its class.

*Proposed:* Change FnExpr.getJavaClass() to return tag as type if it is available.

*Patch:* clj-1378-v2.diff

*Screened by:* Alex Miller

People

Vote (1)
Watch (1)

Dates

  • Created:
    Updated: