On Nov 15, 2010, at 4:41 PM, Alan wrote:

> Yes, the API *does* suggest using seq to check for emptiness. (empty?
> x) is implemented as (not (seq x)). You certainly won't ever get
> improved performance by using empty? - at best you break even, most of
> the time you lose. For example:
> 

The only way the API could suggest using 'seq' to check for emptiness is by not 
having a function called 'empty?'. It's irrelevant that 'empty?' is merely 
implemented as (not (seq)). The function is there for a reason. Are you 
suggesting that it's deprecated? If you would like to focus on a premature 
optimization of this sort, go right ahead. I will stick with the more 
meaningful function name.  If I'm testing whether or not a sequence is empty I 
will use 'empty?'.
> 
> 
> Of course performance isn't usually the main driver, so if you feel
> empty? really is more expressive in your case, go for it. But the OP
> seems to care about performance, and suggesting empty? is off the
> mark.
> 

Apparently you didn't read what I wrote. I didn't suggest that using 'empty?' 
would solve the OP's performance issue. I simply pointed out that he was 
testing two opposite things.

> On Nov 14, 11:42 am, David Sletten <da...@bosatsu.net> wrote:
>> On Nov 14, 2010, at 2:16 PM, Eric Kobrin wrote:
>> 
>>> In the API it is suggested to use `seq` to check if coll is empty.
>> 
>> Your timing results raise some interesting questions, however, the API 
>> doesn't suggest using 'seq' to check if a collection is empty. That's what 
>> 'empty?' is for. The documentation note suggests (for style purposes 
>> apparently) that you use 'seq' to test that the collection is not empty. So 
>> to be precise you are testing two different things below. For instance, 
>> (identical? coll []) is true when coll is an empty vector. (seq coll) is 
>> true when coll is not empty. The correct equivalent would be to test (empty? 
>> coll).
>> 
>> Of course, this doesn't change the results. I get similar timings with 
>> empty?:
>> user=> (let [iterations 100000000] (time (dotimes [_ iterations]
>>                                     (identical? [] []))) (time (dotimes [_ 
>> iterations] (empty? []))))
>> "Elapsed time: 2.294 msecs"
>> "Elapsed time: 2191.256 msecs"
>> nil
>> user=> (let [iterations 100000000] (time (dotimes [_ iterations]             
>>                                                                              
>>                                                                              
>>                                        
>>                                            (identical? "" ""))) (time 
>> (dotimes [_ iterations] (empty? ""))))
>> "Elapsed time: 2.657 msecs"
>> "Elapsed time: 4654.622 msecs"
>> nil
>> user=> (let [iterations 100000000] (time (dotimes [_ iterations]             
>>                                                                              
>>                                                                              
>>                                        
>>                                            (identical? () ()))) (time 
>> (dotimes [_ iterations] (empty? ()))))
>> "Elapsed time: 2.608 msecs"
>> "Elapsed time: 2144.142 msecs"
>> nil
>> 
>> This isn't so surprising though, considering that 'identical?' is the 
>> simplest possible test you could try--do two references point to the same 
>> object in memory? It can't get any more efficient than that.
>> 
>> Have all good days,
>> David Sletten
>> 
>> 
>> 
>>> I was working on some code recently found that my biggest performance
>>> bottleneck was calling `seq` to check for emptiness. The calls to
>>> `seq` were causing lots of object allocation and taking noticeable CPU
>>> time. I switched to using `identical?` to explicitly compare against
>>> the empty vector and was rewarded with a drastic reduction in
>>> execution time.
>> 
>>> Here are some hasty tests showing just how big the difference can be:
>> 
>>> user=> (let [iterations 100000000] (time (dotimes [_ iterations]
>>> (identical? [] []))) (time (dotimes [_ iterations] (seq []))))
>>> "Elapsed time: 3.512 msecs"
>>> "Elapsed time: 2512.366 msecs"
>>> nil
>>> user=> (let [iterations 100000000] (time (dotimes [_ iterations]
>>> (identical? "" ""))) (time (dotimes [_ iterations] (seq ""))))
>>> "Elapsed time: 3.898 msecs"
>>> "Elapsed time: 5607.865 msecs"
>>> nil
>>> user=> (let [iterations 100000000] (time (dotimes [_ iterations]
>>> (identical? () ()))) (time (dotimes [_ iterations] (seq ()))))
>>> "Elapsed time: 3.768 msecs"
>>> "Elapsed time: 2258.095 msecs"
>>> nil
>> 
>>> Has any thought been given to providing a faster `empty?` that is not
>>> based on seq?
>> 
>>> Thanks,
>>> Eric Kobrin
>> 
>>> --
>>> 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

-- 
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

Reply via email to