On Sun, Nov 14, 2010 at 4:33 PM, David Nolen <dnolen.li...@gmail.com> wrote: > On Sun, Nov 14, 2010 at 3:36 PM, Eric Kobrin <erl...@gmail.com> wrote: >> >> In the particular bit of code I'm working on, I have a collection of >> vectors. The last one is always [] and no others are empty. Using >> `identical?` instead of `seq` to detect that last vector shaved quite >> a bit of time in my loop. > > The use of identical? is just wrong. It checks whether two objects are in > fact the same object in memory. The fact that: > (identical? [] []) ; true > is just an implementation detail. The compiler *happened* to use the same > object - it's an optimization for constant literals. Better to use a real > sentinel. > Also such low timings for 1e8 iterations should being a warning sign that > perhaps you are not measuring what you think you are measuring. Your > (identical? [] []) is likely becoming a no-op. > In the general case, if you're using vectors and loop anyway for performance > reasons, (= (count v) 0) to check for a empty vector is plenty fast and > resource efficient.
Interestingly, (= (count v) 0) is relatively fast (900 msec); (seq v) is slower (2s); (empty? v) is even slower (3s); and (= v []) is slowest (16s). As for a real sentinel, nothing beats the old (Object.) -- it's guaranteed not equal to any existing object at time of creation, so no preexisting piece of data in your input will look like a freshly-created one, unlike the case with such traditional sentinels as nil and zero. (The zero sentinel in C strings has caused no end of trouble whenever the input string could have an ASCII NUL in it, and we're all sick to death of Java collections that choke on null elements, keys, or values. ConcurrentHashMap is a notorious culprit there.) (let [sentinel (Object.) v (conj some-vector sentinel)] (loop [...] (if (= sentinel something) ... Another nice thing about (Object.) is that the Object .equals method boils down to the Java == operator, and JIT-optimizes away to same, so the above is just as fast as, and more readable than, (if (identical? sentinel something) ...). Just be sure to put the sentinel first so the object whose method is being called is an unspecialized Object. If it's the other way around something else's .equals gets called, and if it's well designed it will start with if (other == this) return true;, and branch prediction on the JITted code will eventually eliminate the cost of the rest of the method not just being return false;, but you never know. -- 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