The is_not_empty() method as more clearly alternative for !is_empty()

Then what about has_elements(), is_inhabited(), or some 'new-speak' creation, e.g., inhab() ?

As a more general approach, post-fix macros that were discussed for await could also work nicely:

if my_vec.not!(is_empty) { ... }

That said, I think the length of this thread is mostly due to it being a nice and easy bike shed target, not because of some deep need. :wink:

15 Likes

+ :100:


But to have some fun with it, we could also do

not(Vec::is_empty)(&v)
8 Likes

While we're at it, what do you think of:

if v.is_empty() else { … }

I find it tantalizing! :smile:

2 Likes

My head just exploded! Nooooooooooooooooo!

4 Likes

Probably using quantifier here would be the most direct way to express what we want e.g. it works well for Option type with is_some/is_none methods which not only refers to corresponding patterns but as well contains nearly the same meaning as in English language.

All of Vec, Set, Map, etc. could be seen as kinds of Option, since all of these types also share the same possibility of being empty. In this sense they differ from Option only in providing possibility of being filled partially instead of possibility of being whole.

In English when we ask for a whole thing (Option) we use some and when we ask for most likely incomplete thing (Vec, Set, Map, etc.) we use any.

Therefore, is_any could be appropriate method name.

5 Likes

Well, to be complete, we'd need 6 functions:

  • empty
  • not full
  • neither completely empty nor completely full
  • not empty
  • full
  • either completely empy or completely full (but not partially)

IOW, combinations of 1 or 2 out of is_none/empty, is_any/some, and is_all/full.

Don't forget

  • half full
  • half empty

:wink:

3 Likes

You'd want is_nonempty or just nonempty over is_not_empty

This has been brought up before, but has_elements is a better name than is_nonempty.

For consistency it should probably be has_items, since there's remove_item rather than remove_element. But the Vec documentation is pretty inconsistent about item/element anyway :frowning:

9 Likes

The associated types on traits like Iterator are also called Item, and "element" isn't used, to my knowledge, anywhere in std.

Edit: Searching the docs confirms that "element" isn't used in any names

3 Likes

if !string.is_empty() { println!("{}", string) }

if string.has_items() { println!("{}", string) }

if string.has_elements() { println!("{}", string) }

if string.is_nonempty() { println!("{}", string) }

if string.is_not_empty() { println!("{}", string) }

if string.is_any() { println!("{}", string) }


if !slice.is_empty() { println!("{}", slice) }

if slice.has_items() { println!("{}", slice) }

if slice.has_elements() { println!("{}", slice) }

if slice.is_nonempty() { println!("{}", slice) }

if slice.is_not_empty() { println!("{}", slice) }

if slice.is_any() { println!("{}", slice) }


if !buf.is_empty() { println!("{}", buf) }

if buf.has_items() { println!("{}", buf) }

if buf.has_elements() { println!("{}", buf) }

if buf.is_nonempty() { println!("{}", buf) }

if buf.is_not_empty() { println!("{}", buf) }

if buf.is_any() { println!("{}", buf) }


if !names.is_empty() { println!("{}", names) }

if names.has_items() { println!("{}", names) }

if names.has_elements() { println!("{}", names) }

if names.is_nonempty() { println!("{}", names) }

if names.is_not_empty() { println!("{}", names) }

if names.is_any() { println!("{}", names) }

Would you say a vector of length 1 "has elements"? To me is_not_empty seems way less ambiguous.

1 Like

Isn't is_none and is_some from Option what we're looking for. Could be copied to Vec. Alternatively has_none and has_some.

3 Likes

My personal preferred color would be has_any(). In any case, it should probably come with whatever trait is_empty() lands on, and ExactSizeIterator should provide it.

That's why I like the any verbage, as it's close to .iter().any(|_| true). And shouldn't be confusing for collections of Option.

1 Like

Maybe I'm missing something, but what would the point of adding is_none be if is_empty already exists?

I think a postfix not operator would be nice:

if foo.is_empty().! {}

If we implement std::ops::Not for Fn(T) -> bool, we could even write

if foo.is_empty.!() {}
1 Like

So, foo.not(). All you need to do is import std::ops::Not

5 Likes

I was going to propose is_inhabited myself. Then I reflected on a certain subtle distinction between being 'non-empty' and 'inhabited' made in HoTT and constructive mathematics in general. Namely, a proof of a proposition that a set is non-empty establishes only that; it doesn't tell you what its elements are, only that some exist. Whereas a proof that a set is inhabited will exhibit an actual element of it, that you can extract from the proof and refer to later.

Now, how does that relate to programming? Well, usually when you want to check if a vector is inhabited, you don't do that just to satisfy idle curiosity; you actually want to manipulate its elements in some manner. So why instead use APIs that return the element you want (if there is one) wrapped in an Option?

(I believe the issue I raised is usually called 'Boolean blindness'.)

3 Likes

Interesting perspective for types where real work is required to determine the presence of elements. In the case of Vec, though, the number of elements is explicitly stored. That's the most efficient implementation.

For other types this distinction can be truly valuable. I am a big fan of constructivism.