Re: About metadat and #^ macro.
Alan, I'm with you on this one. Reflection is so much slower that sometimes I wish clojure had a different syntax for reflective method invocation. For example: 1) Make reflection an automatic error (not even a warning), and 2) Use another syntax (let's say double-dot, for the sake of argument) to mean I'm OK with this being done via reflection. (.foo bar) = error (.foo ^SomeType bar) = fast (..foo bar) = probably slow Of course, something this fundamental is unlikely to change, so I guess I should just get used to setting *warn-on-reflection* :) - Chris -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: About metadat and #^ macro.
On Thu, Oct 20, 2011 at 3:53 PM, Chris Perkins chrisperkin...@gmail.com wrote: 1) Make reflection an automatic error (not even a warning), and 2) Use another syntax (let's say double-dot, for the sake of argument) to mean I'm OK with this being done via reflection. (.foo bar) = error (.foo ^SomeType bar) = fast (..foo bar) = probably slow Instead of introducing a whole new (possibly confusing) syntax for reflective calls, IMHO it's better to have a var *error-on-reflection* which, when set to true will throw an error on reflection. A patch for this should be easy to implement as well. Regards, BG -- Baishampayan Ghose b.ghose at gmail.com -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: About metadat and #^ macro.
Hey guys, The small loss of performance expression was applied to the specific example I used to illustrate the thing. 500 times longer may look huge but if it occurs 10 times in your application run, bottom line it may mean nothing. Of course if you have a fn chewing up 30% of your application run time, reflection may become significant, hence the need to check. It was not meant as a general remark. It's a trade off situation and you must do some analysis to apply these optimizations. Most of the time here we do not care about the type of objects passed except in some frequently reused common code. We do not want to loose the flexibility of dynamic typing, our message bus runs on a small cluster Atom 330 machines 24/7... not Hulk like servers and we should be the rightly concerned by these optimizations. We did not find so many cases that justified retooling the code up to now. Luc P. On Wed, 19 Oct 2011 22:49:46 -0700 (PDT) Alan Malloy a...@malloys.org wrote: I agree with the general sentiment: add typehints later, and only if you need performance in this particular part of the code. I object to the characterization as a small loss of performance, though. A reflective method call takes about five hundred times as long as a hinted method call in the following benchmark, so if you do have a performance-sensitive section of your program that needs to do a lot of interop, the improvement is dramatic, not small. user (time (dotimes [_ 1e6] (let [s (identity test)] (.length s Elapsed time: 15490.471302 msecs user (time (dotimes [_ 1e6] (let [s (identity test)] (.length ^String s Elapsed time: 34.561754 msecs On Oct 19, 10:35 pm, Luc Prefontaine lprefonta...@softaddicts.ca wrote: Just use ^ for type hints. http://clojure.org/java_interop#Java%20Interop-Type%20Hints Type hints are used to eliminate reflection calls, the compiler can use the exact type of the parameter to eliminate the runtime cost of finding if methods/fields exist before calling/accessing them. user= (set! *warn-on-reflection* true) true ;;; == tells the compiler to complain about reflection calls user= (defn a [b] (.startsWith b a)) Reflection warning, NO_SOURCE_PATH:23 - call to startsWith can't be resolved. === Oups ! #'user/a user= (a 1) java.lang.IllegalArgumentException: No matching method found: startsWith for class java.lang.Integer (NO_SOURCE_FILE:0) This definition has no type hint, the compiler flags a warning to say that it cannot resolve the method startsWith. If you try to call the first form with an object not implementing startsWith, the runtime traps that it did not find the method on that object's class. The flexibility comes with a cost, finding the method on the fly. user= (defn a [^String b] (.startsWith b a)) #'user/a user= (a 1) java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String (NO_SOURCE_FILE:0) Here the compilation does not trigger the reflection warning, the argument type has been hinted as a string. The compiler can find the method immediately and generate the code without any runtime search. At runtime, if you ever call the second form with a non string object, this time you get that the argument type is not the one expected (from the type hint). The compiler has added a type check instead of relying on the dynamic search for methods/fields in the class which is faster. Note that it's not data typing per se. You are allowed to call the form with a different object class. The compiler will not scream, the runtime will if you persists to call the method. Form #1 allows you to pass objects of any class that implements startsWith with a small loss of performance. In form #2 you can gain performance at the expense of generality. Type hints are to be to improve performance AFTER your code is more or less stable. If you use type hints early in your development, you will carry them all the way and that can be a significant pain. Luc P. On Wed, 19 Oct 2011 22:03:31 -0700 (PDT) mmwaikar mmwai...@gmail.com wrote: Hi, I read in Clojure in Action book by Amit Rathore, that #^ associates metadata for the next form. He also mentions that it is deprecated. So what is the current way of doing it? Also, in code like this - (defn filenames-in-jar Returns a sequence of Strings naming the non-directory entries in the JAR file. [#^JarFile jar-file] is it specifying that the type of the jar-file argument should be JarFile? Where can I find some more documentation and or examples about it? Thanks, Manoj. -- Luc P. The rabid Muppet -- Luc P. The rabid Muppet -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts
Re: About metadat and #^ macro.
Thanks everyone for your inputs and the discussion. Manoj. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
About metadat and #^ macro.
Hi, I read in Clojure in Action book by Amit Rathore, that #^ associates metadata for the next form. He also mentions that it is deprecated. So what is the current way of doing it? Also, in code like this - (defn filenames-in-jar Returns a sequence of Strings naming the non-directory entries in the JAR file. [#^JarFile jar-file] is it specifying that the type of the jar-file argument should be JarFile? Where can I find some more documentation and or examples about it? Thanks, Manoj. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: About metadat and #^ macro.
The current syntax is just ^ (defn filenames-in-jar [^JarFile jar-file] ...) On Thu, Oct 20, 2011 at 07:03, mmwaikar mmwai...@gmail.com wrote: Hi, I read in Clojure in Action book by Amit Rathore, that #^ associates metadata for the next form. He also mentions that it is deprecated. So what is the current way of doing it? Also, in code like this - (defn filenames-in-jar Returns a sequence of Strings naming the non-directory entries in the JAR file. [#^JarFile jar-file] is it specifying that the type of the jar-file argument should be JarFile? Where can I find some more documentation and or examples about it? Thanks, Manoj. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: About metadat and #^ macro.
Sunil, I read in Clojure in Action book by Amit Rathore, that #^ associates metadata for the next form. He also mentions that it is deprecated. So what is the current way of doing it? Also, in code like this - (defn filenames-in-jar Returns a sequence of Strings naming the non-directory entries in the JAR file. [#^JarFile jar-file] is it specifying that the type of the jar-file argument should be JarFile? Where can I find some more documentation and or examples about it? The current way of attaching meta-data or type hints to vars is through the ^ reader macro. So your example will look like this - (defn filenames-in-jar [^JarFile jar-file] ...) Regards, BG -- Baishampayan Ghose b.ghose at gmail.com -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: About metadat and #^ macro.
Just use ^ for type hints. http://clojure.org/java_interop#Java%20Interop-Type%20Hints Type hints are used to eliminate reflection calls, the compiler can use the exact type of the parameter to eliminate the runtime cost of finding if methods/fields exist before calling/accessing them. user= (set! *warn-on-reflection* true) true ;;; == tells the compiler to complain about reflection calls user= (defn a [b] (.startsWith b a)) Reflection warning, NO_SOURCE_PATH:23 - call to startsWith can't be resolved. === Oups ! #'user/a user= (a 1) java.lang.IllegalArgumentException: No matching method found: startsWith for class java.lang.Integer (NO_SOURCE_FILE:0) This definition has no type hint, the compiler flags a warning to say that it cannot resolve the method startsWith. If you try to call the first form with an object not implementing startsWith, the runtime traps that it did not find the method on that object's class. The flexibility comes with a cost, finding the method on the fly. user= (defn a [^String b] (.startsWith b a)) #'user/a user= (a 1) java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String (NO_SOURCE_FILE:0) Here the compilation does not trigger the reflection warning, the argument type has been hinted as a string. The compiler can find the method immediately and generate the code without any runtime search. At runtime, if you ever call the second form with a non string object, this time you get that the argument type is not the one expected (from the type hint). The compiler has added a type check instead of relying on the dynamic search for methods/fields in the class which is faster. Note that it's not data typing per se. You are allowed to call the form with a different object class. The compiler will not scream, the runtime will if you persists to call the method. Form #1 allows you to pass objects of any class that implements startsWith with a small loss of performance. In form #2 you can gain performance at the expense of generality. Type hints are to be to improve performance AFTER your code is more or less stable. If you use type hints early in your development, you will carry them all the way and that can be a significant pain. Luc P. On Wed, 19 Oct 2011 22:03:31 -0700 (PDT) mmwaikar mmwai...@gmail.com wrote: Hi, I read in Clojure in Action book by Amit Rathore, that #^ associates metadata for the next form. He also mentions that it is deprecated. So what is the current way of doing it? Also, in code like this - (defn filenames-in-jar Returns a sequence of Strings naming the non-directory entries in the JAR file. [#^JarFile jar-file] is it specifying that the type of the jar-file argument should be JarFile? Where can I find some more documentation and or examples about it? Thanks, Manoj. -- Luc P. The rabid Muppet -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: About metadat and #^ macro.
I agree with the general sentiment: add typehints later, and only if you need performance in this particular part of the code. I object to the characterization as a small loss of performance, though. A reflective method call takes about five hundred times as long as a hinted method call in the following benchmark, so if you do have a performance-sensitive section of your program that needs to do a lot of interop, the improvement is dramatic, not small. user (time (dotimes [_ 1e6] (let [s (identity test)] (.length s Elapsed time: 15490.471302 msecs user (time (dotimes [_ 1e6] (let [s (identity test)] (.length ^String s Elapsed time: 34.561754 msecs On Oct 19, 10:35 pm, Luc Prefontaine lprefonta...@softaddicts.ca wrote: Just use ^ for type hints. http://clojure.org/java_interop#Java%20Interop-Type%20Hints Type hints are used to eliminate reflection calls, the compiler can use the exact type of the parameter to eliminate the runtime cost of finding if methods/fields exist before calling/accessing them. user= (set! *warn-on-reflection* true) true ;;; == tells the compiler to complain about reflection calls user= (defn a [b] (.startsWith b a)) Reflection warning, NO_SOURCE_PATH:23 - call to startsWith can't be resolved. === Oups ! #'user/a user= (a 1) java.lang.IllegalArgumentException: No matching method found: startsWith for class java.lang.Integer (NO_SOURCE_FILE:0) This definition has no type hint, the compiler flags a warning to say that it cannot resolve the method startsWith. If you try to call the first form with an object not implementing startsWith, the runtime traps that it did not find the method on that object's class. The flexibility comes with a cost, finding the method on the fly. user= (defn a [^String b] (.startsWith b a)) #'user/a user= (a 1) java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String (NO_SOURCE_FILE:0) Here the compilation does not trigger the reflection warning, the argument type has been hinted as a string. The compiler can find the method immediately and generate the code without any runtime search. At runtime, if you ever call the second form with a non string object, this time you get that the argument type is not the one expected (from the type hint). The compiler has added a type check instead of relying on the dynamic search for methods/fields in the class which is faster. Note that it's not data typing per se. You are allowed to call the form with a different object class. The compiler will not scream, the runtime will if you persists to call the method. Form #1 allows you to pass objects of any class that implements startsWith with a small loss of performance. In form #2 you can gain performance at the expense of generality. Type hints are to be to improve performance AFTER your code is more or less stable. If you use type hints early in your development, you will carry them all the way and that can be a significant pain. Luc P. On Wed, 19 Oct 2011 22:03:31 -0700 (PDT) mmwaikar mmwai...@gmail.com wrote: Hi, I read in Clojure in Action book by Amit Rathore, that #^ associates metadata for the next form. He also mentions that it is deprecated. So what is the current way of doing it? Also, in code like this - (defn filenames-in-jar Returns a sequence of Strings naming the non-directory entries in the JAR file. [#^JarFile jar-file] is it specifying that the type of the jar-file argument should be JarFile? Where can I find some more documentation and or examples about it? Thanks, Manoj. -- Luc P. The rabid Muppet -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en