Collections: `any?` vs `!empty`

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.

Yes, I realized that just after posting. But I still think the non-block form makes no sense. Relying on thruthy values without the block just feels wrong to me. If I wanted that behavior I would probably write that like any? { |e| !!e }, but I finding it hard to think of an example where I would use that particular check.

1 Like

Why not just deprecate any? (without block) and then remove it entirely?

Sometimes a little extra “cognitive load” and correctness is better than weird errors that show up far away from where someone used any? instead of !empty?. While some things make sense for personal choice/style, this is programming after all and correctness is better.

Perhaps a linguist can explain why we don’t have a word in English for “not empty”. My armchair theory is that “not empty” is actually less cognitive load, since “empty” is very clear; we have a lot of words for > 0 because, well, that’s !empty cognitive load. :slight_smile:

My 7 cents (inflation).


Oh please no, that kind of thinking leads down the road where raise "no items?" unless collection.any? ends up as

if collection.empty?
  raise "no items?"

That is, makes Crystal look exactly like any other mainstream language. It’s the expressiveness that made me love Ruby and in turn Crystal.

Yes please, “correctness” be damned. While technically it’s doing two different things with and without a block, it obviously makes sense to people, proven by the fact that we have to make a linter rule to point out that it doesn’t do what people expect.

Expressiveness isn’t really at stake here, these are equivalent in all ways when you’re not dealing with falsey collections (yes all, see this message by straight-shoota):

raise "no items?" unless collections.any?
raise "no items?" if collections.empty?

The latter better conveys its intent, whereas the former implies any items being in the collection, any items being truthy, or other interpretations.

Personally, I don’t reach for block-less #any? in my projects, and if I were to do something of that nature then I would write .any? &.itself or .none? &.nil?. I’m not sure if this functionality should be changed or the overload removed entirely, but any decisions made should also be applied to its block-less counterpart methods #all?, #one? and #none? which also fall under this issue.

I also think that the rule should be removed as it only really applies to falsey collections which Ameba has no way of determining because it does not perform semantic analysis; assuming that all collections are falsey for the sake of this rule doesn’t feel right to me. There are also no equivalent rules for the counterpart methods (e.g. using #none? over #empty?).


I wouldn’t say that. Conceptually (but also literally), any? without a block just provides a default block, so it’s just a matter of what that block does. Currently it returns the element from the block, but if we changed the default block to return true, it does what folks actually expect:

module Enumerable(T)
  def any?
    any? { true }

[nil].any? # => true

The downside is that — unless this functionality is considered a bug, and I don’t think it is — it’s not a change that can safely be made until v2.0 due to Crystal’s observance of SemVer.

1 Like

I was aiming at the argument for removing blockless any? which I read as “!empty? is all we need”, and imagined the same argument being put forth in favor of killing unless (I believe it’s been put forward), and had a “death by a thousand cut” scenario playing out in my head.

I might be scarred by some coding styles in vogue in PHP which forbids the use of empty() as it considers both null, 0, the empty array and the empty string as being, indeed, empty, and thus not type-strong and therefore non-kosher. Which totally ignores the fact it can be quite handy in practice that you can express $var && $var !== '' as a simple English expression.

I think that’s a good argument for keeping it as it is.

Outlawing one construct completely for a small chance that you’re shooting yourself in the foot is overkill.

I’ll backpedal on the idea of changing the default block after reading @Devonte’s argument, and rereading @straight-shoota’s point that it’s only collections including Nil, Bool, or Pointer where any? isn’t practically the same thing as !empty? (and even then, in some cases considering an array of only nil values empty, could be handy).

I have posted a feature proposal for Enumerable#present? on the issue tracker: Introduce `Enumerable#present?` · Issue #13847 · crystal-lang/crystal · GitHub


I was aiming at the argument for removing blockless any? which I read as “!empty? is all we need”, and imagined the same argument being put forth in favor of killing unless (I believe it’s been put forward), and had a “death by a thousand cut” scenario playing out in my head.

Worry not, as I am sure most of us who enjoy Crystal continue to enjoy Ruby and have no desire to change the language. :slight_smile:

Well, it wasn’t an example pulled out of thin air: unless is redundant keyword? · Issue #13678 · crystal-lang/crystal · GitHub

But it’s interesting following these discussions about how the language (or the ecosystem) might evolve. There are different kinds of “mindset” in the developer population, which become very visible in some circumstances. Sometimes even in the same language. In PHP most are following the very Java-ish way of Symfony, but there’s a bastion around Laravel that’s obviously very Rails/Ruby inspired. Funny how these thing goes.


Single issue doesn’t contradict “most of us” statement.