Clojure

eval reader fail to recognize function object

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Declined
  • Affects Version/s: Release 1.3
  • Fix Version/s: None
  • Component/s: None
  • Labels:

Description

(defmacro stubbing [stub-forms & body]
  (let [stub-pairs (partition 2 stub-forms)
        returns (map last stub-pairs)
        stub-fns (map constantly returns)  ;;(map #(list 'constantly %) returns)
        real-fns (map first stub-pairs)]
    `(binding [~@(interleave real-fns stub-fns)]
       ~@body)))

This macro is from Clojure In Action , whith the commented line rewrited (I know that original is better)
I assumed that this macro would work as supposed , if the stub forms use compile time literal, for e.g

(def ^:dynamic $ (fn [x] (* x 10))


(stubbing [$ 1]
        ($ 1 1))
;; =>
IllegalArgumentException No matching ctor found for class clojure.core$constantly$fn__3656
	clojure.lang.Reflector.invokeConstructor (Reflector.java:166)
	clojure.lang.LispReader$EvalReader.invoke (LispReader.java:1031)
	clojure.lang.LispReader$DispatchReader.invoke (LispReader.java:618)

;;macro can expanded  
(macroexpand-all '(stubbing [$ 1]
                ($ 1 1)))
;; =>
(let* [] (clojure.core/push-thread-bindings (clojure.core/hash-map (var $) #<core$constantly$fn__3656 clojure.core$constantly$fn__3656@161f888>)) (try ($ 1 1) (finally (clojure.core/pop-thread-bindings))))

I thought there is something wrong with eval reader, but i can't figure it out

btw the above code can run on clojure-clr

Activity

Hide
Alex Miller added a comment -

Per discussion in comments and other tickets

Show
Alex Miller added a comment - Per discussion in comments and other tickets
Hide
Greg Chapman added a comment -

It appears CLJ-1928 has been opened to improve the error message. So this issue should probably be closed.

Show
Greg Chapman added a comment - It appears CLJ-1928 has been opened to improve the error message. So this issue should probably be closed.
Hide
Steve Miner added a comment -

Sounds like a duplicate of CLJ-1206 which was recently declined. There are some potential work-arounds in that bug.

Show
Steve Miner added a comment - Sounds like a duplicate of CLJ-1206 which was recently declined. There are some potential work-arounds in that bug.
Hide
Greg Chapman added a comment -

FWIW, This still happens with Clojure 1.8. I believe what happens, is, when given a value of type Fn (like that produced by a call to constantly), the compiler's emitValue method will call RT.printString. This will result in a call to print-dup on the value, producing a string like this:

#=(clojure.core$constantly$fn__4614. )

So the LispReader will try to evaluate a call to a 0-argument constructor for the Fn object. This will not work for a closure (such as that produced by constantly), since the closure needs the values closed-over to be supplied to its constructor (so there is no matching ctor).

This could probably have some better error message; I ran into it today and it took me awhile to understand why the EvalReader was even coming into play.

Show
Greg Chapman added a comment - FWIW, This still happens with Clojure 1.8. I believe what happens, is, when given a value of type Fn (like that produced by a call to constantly), the compiler's emitValue method will call RT.printString. This will result in a call to print-dup on the value, producing a string like this:
#=(clojure.core$constantly$fn__4614. )
So the LispReader will try to evaluate a call to a 0-argument constructor for the Fn object. This will not work for a closure (such as that produced by constantly), since the closure needs the values closed-over to be supplied to its constructor (so there is no matching ctor). This could probably have some better error message; I ran into it today and it took me awhile to understand why the EvalReader was even coming into play.
Hide
Naitong Xiao added a comment -

I use clojure 1.3

The example in Clojure In Action is Ok on clojure 1.3
I just found this peculiar thing when trying to answer a question from another one in a mail list.

Show
Naitong Xiao added a comment - I use clojure 1.3 The example in Clojure In Action is Ok on clojure 1.3 I just found this peculiar thing when trying to answer a question from another one in a mail list.
Hide
Michael Klishin added a comment -

As far as I know, Clojure in Action examples are written for Clojure 1.2. What version are you using?

Show
Michael Klishin added a comment - As far as I know, Clojure in Action examples are written for Clojure 1.2. What version are you using?

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: