On Mon, Aug 31, 2009 at 10:55 AM, Krukow<karl.kru...@gmail.com> wrote: > > I have two minor minor suggestions for Clojure changes. > > 1) Consider this function: > user> (set! *warn-on-reflection* true) > true > user> (defn reader-from-classpath [s] > (-> (.getResourceAsStream java.lang.String s) > (java.io.InputStreamReader.) > (java.io.BufferedReader.))) > Reflection warning, NO_SOURCE_PATH:2 - call to getResourceAsStream > can't be resolved. > #'user/reader-from-classpath > > In general, I think every call of form (.instanceMember Classname > args*) will generate such a warning since it expands to, e.g., > > user> (macroexpand ' (.getResourceAsStream java.lang.String s)) > (. (clojure.core/identity java.lang.String) getResourceAsStream s) > user> > > And identity doesn't have any type information. A simple fix would be. > user> (defn #^Class class-identity [#^Class c] c) > > #'user/class-identity > > and then expanding (.instanceMember Classname args*) to > > (. (class-identity Classname) instanceMember args*) > > ------- > > 2) I can do: > user> (into {} '([:k :v])) > {:k :v} > > This works for two-element vectors. However, I cannot do the same for > two-element arrays: > > user> (def str_array (.split "k=v" "=")) > #'user/str_array > user> (into {} (list str_array)) > ; Evaluation aborted. > > It would be a simple addition to clojure.lang.ATransientMap: > import java.lang.reflect.Array;//change > ... > public ITransientMap conj(Object o) { > ensureEditable(); > if(o instanceof Map.Entry) > { > Map.Entry e = (Map.Entry) o; > > return assoc(e.getKey(), e.getValue()); > } > else if(o instanceof IPersistentVector) > { > IPersistentVector v = (IPersistentVector) o; > if(v.count() != 2) > throw new IllegalArgumentException("Vector arg > to map conj must be > a pair"); > return assoc(v.nth(0), v.nth(1)); > }//begin change > else if(o != null && o.getClass().isArray()) > { > if(Array.getLength(o) != 2) > throw new IllegalArgumentException("Array arg > to map conj must > have exactly two elements"); > return assoc(Array.get(o,0), Array.get(o,1)); > }//end change > > ITransientMap ret = this; > for(ISeq es = RT.seq(o); es != null; es = es.next()) > { > Map.Entry e = (Map.Entry) es.first(); > ret = ret.assoc(e.getKey(), e.getValue()); > } > return ret; > } > > After this change I have: > user> (def str_array (.split "k=v" "=")) > #'user/str_array > user> (into {} (list str_array)) > {"k" "v"} > user> > > The use-case arose from wanting to create a map from a properties file > using split ("=") on each line of the properties file (and not wanting > to copy the array into []). > > N.B. the cost is an additional null-check and o.getClass().isArray(). > > What do you guys think?
#1 is fine idea. I've implemented the hinting in the compiler where that expansion takes place. (commit e45046da8f) As for #2, I'm less sure I want to encourage people to interoperate with the map library using arrays. Rich --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---