Project

General

Profile

Feature #12075

some container#nonempty?

Added by naruse (Yui NARUSE) almost 4 years ago. Updated about 3 years ago.

Status:
Feedback
Priority:
Normal
Target version:
-
[ruby-core:73824]

Description

I sometimes write following code.

ary = some_metho_returns_nil_or_empty_container() # nil or "" or [] or {}

if ary && !ary.empty?
  #  some code
end

But the condition ary && !ary.empty? is too long and complex.
Though Ruby 2.3 introduces &., but this can’t be written as ary&.empty?.

One idea is add nonempty? write as ary&.nonempty?.

akr: nonempty? is not good name because human is not good at handling

This discussion matches following core classes:

  • String
  • Array
  • Hash

Related issues

Related to Ruby master - Feature #13395: Add a method to check for not nilOpenActions

History

Updated by mrkn (Kenta Murata) almost 4 years ago

How about ary.include_something? ?

Updated by akr (Akira Tanaka) almost 4 years ago

How about "some?".

Updated by sawa (Tsuyoshi Sawada) almost 4 years ago

That is a use case for Rails' blank? (or present?).

class Object
  def blank?
    respond_to?(:empty?) ? !!empty? : !self
  end
end

unless ary.blank?
  #  some code
end

What about incorporating these methods from Rails?

Updated by rosenfeld (Rodrigo Rosenfeld Rosas) almost 4 years ago

+1 for bringing blank? and present? to Ruby core. I often use (a || '').empty? checks for not having to depend on ActiveSupport directly in my Ruby code. I'd love to see them in Ruby core though.

Updated by shyouhei (Shyouhei Urabe) almost 4 years ago

No, the OP wants to detect things that are not empty. This is not what blank? means. Also note that blank? in ActiveSupport has different (far more Rails-centric) semantics than what is described in #3.

https://github.com/rails/rails/blob/b3eac823006eb6a346f88793aabef28a6d4f928c/activesupport/lib/active_support/core_ext/object/blank.rb#L115

Updated by sawa (Tsuyoshi Sawada) almost 4 years ago

Shyouhei Urabe wrote:

No, the OP wants to detect things that are not empty. This is not what blank? means.

Yes, I meant that blank? is the opposite of what OP wants. present? is what the OP wants. I replaced if in the original example with unless, so it is the same (Or, to retain if, present? can be used).

ActiveSupport has different (far more Rails-centric) semantics than what is described in #3.

I see.

Updated by rosenfeld (Rodrigo Rosenfeld Rosas) almost 4 years ago

The implementation doesn't have to be the same as the one implemented by ActiveSupport. I think it would be fine to simply check for nil? and empty?. But I'd like to keep the names present? and blank? anyway.

Updated by shevegen (Robert A. Heiler) almost 4 years ago

Perhaps the name .contains? might be good?

Although, .include? sort of is more or less synonymous with .contains? so perhaps this is not a good choice either.

.nonempty? seems a bit long, .non_empty? would be even longer :)

.empty? is a very good name already, I am not sure if "! .empty?" has a good name, though ruby uses the keyword "not"
already. Could use .notempty? haha sorry, I have no good suggestion for a fitting name for negation either, but I am
totally fine with the idea and functionality of the proposal itself, it's a good one.

Updated by shyouhei (Shyouhei Urabe) almost 4 years ago

I have just learned that zsh(1) calls this concept being "full". http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Qualifiers

Updated by sawa (Tsuyoshi Sawada) almost 4 years ago

What about introducing NilClass#empty?:

nil.empty? # => true

The code in question can be written simply as:

unless ary.empty?
  #  some code
end

If the original proposal is going to be realized, then a new method would have to be added to NilClass, String, Array, and Hash, but my proposal makes use of the existing method empty?, and needs to add to only NilClass, keeping the change minimal.

Even if the original proposal is going to be realized, extending empty? as above would make it the complete opposite of such method, and would introduce parallelism.

Updated by rosenfeld (Rodrigo Rosenfeld Rosas) almost 4 years ago

I like this idea a lot, Tsuyoshi. I'm +1 for introducing nil.empty? as returning true.

Updated by nobu (Nobuyoshi Nakada) almost 4 years ago

First, along this line, we'll need negative forms for all predicate methods.

And I think nil.empty? makes no sense.

Just an idea:

module Kernel
  def not(*a)
    not a.empty? ? self : __send__(*a)
  end
end

ary = nil;   ary&.not(:empty?) #=> nil
ary = [];    ary&.not(:empty?) #=> false
ary = [nil]; ary&.not(:empty?) #=> true

Updated by nobu (Nobuyoshi Nakada) almost 4 years ago

Or

module Kernel
  def !(*a)
    a.empty? ? super() : !__send__(*a)
  end
end

ary = nil;   ary&.!:empty? #=> nil
ary = [];    ary&.!:empty? #=> false
ary = [nil]; ary&.!:empty? #=> true

Updated by phluid61 (Matthew Kerwin) almost 4 years ago

Nobuyoshi Nakada wrote:

First, along this line, we'll need negative forms for all predicate methods.

And I think nil.empty? makes no sense.

Just an idea:

module Kernel
  def not(*a)
    not a.empty? ? self : __send__(*a)
  end
end

ary = nil;   ary&.not(:empty?) #=> nil
ary = [];    ary&.not(:empty?) #=> false
ary = [nil]; ary&.not(:empty?) #=> true

I like this proposal. I definitely prefer the word 'not' over the symbol '!', because ary&.!:empty? has too much consecutive punctuation for my eyes.

Would there be value in extending it to accept a block?

module Kernel
  def not(*a, &b)
    not a.empty? ? self : __send__(*a, &b)
    # or even:
    #not a.empty? ? (b ? (yield self) : self) : __send__(*a, &b)
  end
end

ary = [];  ary&.not(:any?){|x|x>0} #=> true
ary = [1]; ary&.not(:any?){|x|x>0} #=> false

Updated by nobu (Nobuyoshi Nakada) over 3 years ago

  • Description updated (diff)

Updated by naruse (Yui NARUSE) over 3 years ago

  • Status changed from Assigned to Feedback

Array#any? seems to work usual use cases.
Feedback if another cases are discovered.

Updated by sorah (Sorah Fukumori) about 3 years ago

I know any? works on some use cases, but I'm positive to have a proposed method because using any? has a pitfall. We have to guarantee an array doesn't have only false or nil. Also I'm worrying users who started to use any? for this use case, but doesn't know this pitfall.

I'm positive on Object#not idea.

#20

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

Also available in: Atom PDF