Re: About metadat and #^ macro.

2011-10-20 Thread Chris Perkins
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.

2011-10-20 Thread Baishampayan Ghose
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.

2011-10-20 Thread Luc Prefontaine
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.

2011-10-20 Thread mmwaikar
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.

2011-10-19 Thread mmwaikar
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.

2011-10-19 Thread Ben Smith-Mannschott
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.

2011-10-19 Thread Baishampayan Ghose
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.

2011-10-19 Thread Luc Prefontaine
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.

2011-10-19 Thread Alan Malloy
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