Collections: `any?` vs `!empty`

I’m going to agree with both side so far - I find the !empty? to be cognitively heavier than it needs to be, and the current any? only working as expected when the collection type is none falsey is unintuitive and likely to cause problems.

Would it make sense to special case the any? method that doesn’t take a block argument to only check if the collection is not empty, regardless of truthy or falsey types?

When I read the block argument version, I instinctively translate to “are there any elements in this collection that look like this?”, while for the none blocked version I translate “are there any elements in this collection?”. The truthy VS falsey aspect is none intuitive to me unless I know it’s a holdover from the blocked version of the method. I the values of the collection matter to me in a truthy VS falsey way, I think I’d first try naively any?(&.itself). Maybe that’s just me, though.


@straight-shoota Btw, where’s the double-negation in the first place? Empty is a state, it’s not a negation. The whole thing reads exactly like it should - as an answer to a question Whether the collection is empty?, No, it’s not empty.

1 Like

Yes, that’s exactly what I’m wondering about.

If we only talk about the specific circumstances of this instance or the general axiom to avoid any?, we’re not getting to the root of the problem.
I think Enumerable#any? is wrong.
The mere presence of a linter rule that explicitly and unrestrictively suggests to not use it, is a clear sign that something is at odds.

There are two meanings associated with any?:

  1. Are there any elements in the collection.
  2. Are there any truthy elements in the collection.

That’s a subtle difference, but for most cases it doesn’t matter because both semantics align.
The intention of Enumerable#any? is 2. but people tend to expect 1. That’s exactly what the ameba rule is about, to address the probable misconception about any?.

I think the semantics should rightfully prioritize 1. That’s what a reader implicitly assumes and it’s a far more common use case than 2.

Now changing this would be hard. It’s a breaking change and it’s a silent change of behaviour.

Maybe a possible route could be to deprecate Enumerable#any? for collections that can contain falsey types. That’s currently not possible, but we could enhance the compiler to allow issuing deprecations from macros. Then we could drop that in the next major release to make a hard break, and following that we could introduce it again in a minor release. That’s of course a long journey, but maybe it’s worth it?

An alternative solution would be if we could find another method name to express 1. semantics, then we could introduce that independently of any?. But I don’t have much hope for that.


Yes, empty is a state. But I don’t care about empty, I care about knowing if there is any element. Empty is the negation of that state. With negating that again to get what I actually need, I’m using a double negation.

size > 0 expresses the intent correctly, but it’s not a good implementation for generic connections. Enumerable#size actually counts all the elements. At best that only leads to bad performance. But it can have worse effects such as invalidating the entire collection or entering an infinite loop (Remove iteration in Enumerable#size · Issue #10014 · crystal-lang/crystal · GitHub).

This is not mentioned yet, but Indexable#presence could be an option too, considering its roots in Rails


Thankfully most collections will be of the types that actually provide a more efficient implementation, like Arrays.

1 Like

I personally tend to avoid any? too because of the extra meaning. Would be nice to have a present? or some? method that just is the same as !empty?.


Not read the full thread, but obviously any? is not same as !empty?, the invert version of any? is none?, but empty? only check if the count of elements is zero.

See following ruby example:

[8] pry(main)> [nil,false].any?
=> false
[9] pry(main)> [nil,false].none?
[10] pry(main)> ![nil,false].empty?
=> true

Have any? and any_truthy? seems to me as the best option (for crystal 2.x), maybe because I’m not a native english speaker but for a long time I thought that any? was the inverse of empty?.


If we could start from scratch, I would have the non block versions just rely on counts.

I think it could be a valid path forward behind some flag, so that when 2.0 lands that’s the behavior.


I like this idea: Without the flag, a deprecation warning telling to use any_truthy?, with the flag, no warnings and any? behaving like !empty?.

1 Like

I’ll just say that I’m the type that’ll take the readability of any? even with the gotchas. Just like I’ll use if ($something) in PHP rather than if (!empty($something)), even though I know they’re not quite the same thing (and protect myself against the edge cases in other ways).

Changing the semantics of Enumerable#any? would be nice. But it’s gonna take a long time.

So I’m thinking about a solution that can be implemented in a reasonable time frame.
I’d like to introduce a new method for determining if the collection contains any elements. It would return the negation of #empty?.

Following Collections: `any?` vs `!empty` - #10 by HertzDevil Enumerable#present? could be an option.
I’m a bit vary about this because it’s related to String#presence which considers whitespace as empty. So these semantics would be comparable to falsey items in a collection.

Another option would be Enumerable#populated?. It’s a bit longer but maybe a bit less ambiguous?


1 Like

By the way, this is how #presence and friends would look like in Crystal if we copy ActiveSupport’s definitions:

class Object
  def blank? : Bool
    responds_to?(:empty?) ? !!empty? : !self

  def present? : Bool

  def presence : self?
    self unless blank?

struct Nil
  def blank?

class String
  def blank?
    # same as before

ActiveSupport considers collections with blank? elements to be present?, so only String has the special treatment regarding spaces, and [nil, false].presence would return itself. (I’m not sure about the purpose of the other overrides.)


I have never used any in the sense of !empty?

In my Japanese mis-understanding of English, I feel that it is normal for any to take a block. In Japanese, any is translated as “どれか(なにか) ~ がある” and the “~” usually acts as a block. It is not impossible to mean “there is more than zero” by not passing the block “~”, but but such sentences are rare.

  1. Are there any elements in the collection.
  2. Are there any truthy elements in the collection.

I just learned that 1 is preferred in English. If I have to choose between one of the two, I would definitely prefer to keep 2. I like the idea of present or some. (However, this is my personal choice and I would like to follow the community’s opinion.)

I remember that this kind of issue was discussed on slack ruby-jp before, but I don’t remember how the discussion went because slack deletes old posts…


With ChatGPT i was only able to find a few words that would match:

  • present?
  • populated?
  • filled?

My personal suggestion is some?, like in items.some? or errors.some?. But i am not a native speaker, so i’m not 100% sure whether some? would be a good fit. My second choice would be present?.

1 Like

stares in Lucky :grimacing:

(Using my C# glasses), It would make more sense to me if any?took a block, like:

arr = [1, 2, 3, 4, 5]
arr.any? { |e| e > 3 } # returns true
arr.any? { |e| e > 7 } # returns false

while empty? would never take a block.

The specifik case where no block is provided I think any? should behave just like !empty?

And if we feel like !empty? feels like double negation, maybe we could replace it with some?and none? to make it easier tto express both cases?

#any? does have an overload that accepts a block, exactly as you suggest.
This discussion is about the overload without a block.