Add String#notempty? method (#9)

Submitted by: Bertram Scharpf

This revision by: Bertram Scharpf

Date: Wed Mar 21 15:08:06 -0500 2007

ABSTRACT

Add a method String#notempty? analogous to Numeric#nonzero?. The method should return nil when the String is empty.

PROBLEM

I encountered need of a method like this several times. The last two were:

- Converting an olde fixed-with data field to SQL where strings are not terminated but filled up with spaces.

sqlvalue = record[ 4, 30].rstrip.notempty?
This will insert SQL-NULL when the field was empty.

- SQL-like coalesce:

defaulted = str.notempty? || "(void)"

PROPOSAL

Extend `string.c’ by 6 to 8 lines of code. See Implementation below.

ANALYSIS

This change would be trivial. Backwards compatibility problems are not to be expected.

Implementation by plugin would be more uneffective as the macro RSTRING_LEN will not be available by itself.

Another lookahead implementation I use is:

class String method_defined? :notempty? or def notempty? self unless empty? end end

IMPLEMENTATION

static VALUE rb_str_notempty(VALUE str) { if (RSTRING_LEN(str) 0) return Qnil; return str; } or even static VALUE rb_str_notempty(VALUE str) { return RSTRING_LEN(str) 0 ? Qnil : str; }

This should be preceded by a comment like

/ call-seq: str.notempty? => nil or self Returns self if and only if str is not empty, nil otherwise. “hello”.notempty? #=> “hello” ””.notempty? #=> nil /

And later on:

void Init_String(void) { ... rb_define_method(rb_cString, “notempty?”, rb_str_notempty, 0); ... }

Comments

from Jonas Pfenniger, Wed Mar 21 15:37:11 -0500 2007

> Add a method String#notempty? analogous to Numeric#nonzero?. The method should return nil when the String is empty.

With the same logic, a negative counterpart to every `?`ending method
should be created ?

For the fun, I made a small script to count the number of `?`ending methods:
---
mmm = []
ObjectSpace.each_object(Class) do |obj|
  (obj.private_instance_methods + obj.protected_instance_methods +
obj.public_instance_metho
    if m =~ /\?$/ and m !~ /^(not|non)/
      mmm << m
    end
  end
end
require 'pp'
pp mmm.uniq.size
---

That gives me 67 on ruby 1.8.5 without rubygems.

What I would prefer, is the `not` keyword to be accepted in the cases
you cite, like :

x = not "".empty?

which is more readable than :

x = ! "".empty?

and should make you happy :)


from Jacob L Fugal, Wed Mar 21 18:19:54 -0500 2007

On 3/21/07, zimbatm@oree.ch <zimbatm@oree.ch> wrote:
> With the same logic, a negative counterpart to every `?`ending method
> should be created ?
> ...
>
> What I would prefer, is the `not` keyword to be accepted in the cases
> you cite, like :
>
> x = not "".empty?
>
> which is more readable than :
>
> x = ! "".empty?
>
> and should make you happy :)

Actually, the usage is different than you're expecting. The real key
(which isn't mentioned in the RCR) is the return value when the
receiver is *not* empty. As opposed to most ? methods, it returns self
in the true case rather than "true". I was about to write an email
about how this felt "wrong", but then decided to check how nonzero?
behaves, and sure enough, it is analogous:

  >> 5.nonzero? # => 5
  >> 1.nonzero? # => 1
  >> 0.nonzero? # => nil

This behavior surprised me, so I'm still not certain how I feel about
copying the behavior for nonempty?, but Bertram does have some basis
for it. :)

The rationale behind this is then the ability to say:

  my_variable.nonzero? || default_value
  my_variable.notempty? || default_value

If my variable holds a non-zero/non-empty value, the original value is
kept; if it holds a zero or an empty string, the default value is used
(by returning nil). I'll admit this usage does seem handy, but the
name of the methods don't reveal this "feature", which I think is a
flaw. Just like you, I had *thought* that nonzero? and notempty? would
be equivalent to !zero? and !empty?, respectively, because of the
name.

In the end, I'm not opposed to having *a* method with this
functionality, and by analogy to nonzero?, the name bears a measure of
consistency, but I'd still prefer a more revealing name for the
method.

Jacob Fugal

from David Black, Wed Mar 21 19:28:19 -0500 2007

Hi --

I don't think everyone got Jonas Pfenniger's comment, so I'm
cut-and-pasting it here.

Also, I've (hopefully) fixed the thing where the URL has the ID number
instead of the RCR number :-)

Here's Jonas's comment.  See also Jacob's reply, in another subthread.


David

--------------------------------------------------------------------------------------------------------------------------
> Add a method String#notempty? analogous to Numeric#nonzero?. The method should return nil when the String is empty.

With the same logic, a negative counterpart to every `?`ending method
should be created ?

For the fun, I made a small script to count the number of `?`ending methods:
---
mmm = []
ObjectSpace.each_object(Class) do |obj|
  (obj.private_instance_methods + obj.protected_instance_methods +
obj.public_instance_metho
    if m =~ /\?$/ and m !~ /^(not|non)/
      mmm << m
    end
  end
end
require 'pp'
pp mmm.uniq.size
---

That gives me 67 on ruby 1.8.5 without rubygems.

What I would prefer, is the `not` keyword to be accepted in the cases
you cite, like :

x = not "".empty?

which is more readable than :

x = ! "".empty?

and should make you happy :)



from Trans Onoma, Wed Mar 21 20:33:22 -0500 2007

On 3/21/07, lukfugl@gmail.com <lukfugl@gmail.com> wrote:
> A comment about: RCR 9: Add String#notempty? method
> was sent by Jacob L Fugal.
>
> To send a comment, reply to this mail.  Please trim all unnecessary
> lines.
>
> You can view RCR 9 at:
> https://rcrchive.net/rcrs/15
>
> On 3/21/07, zimbatm@oree.ch <zimbatm@oree.ch> wrote:
> > With the same logic, a negative counterpart to every `?`ending method
> > should be created ?
> > ...
> >
> > What I would prefer, is the `not` keyword to be accepted in the cases
> > you cite, like :
> >
> > x = not "".empty?
> >
> > which is more readable than :
> >
> > x = ! "".empty?
> >
> > and should make you happy :)
>
> Actually, the usage is different than you're expecting. The real key
> (which isn't mentioned in the RCR) is the return value when the
> receiver is *not* empty. As opposed to most ? methods, it returns self
> in the true case rather than "true". I was about to write an email
> about how this felt "wrong", but then decided to check how nonzero?
> behaves, and sure enough, it is analogous:
>
>   >> 5.nonzero? # => 5
>   >> 1.nonzero? # => 1
>   >> 0.nonzero? # => nil
>
> This behavior surprised me, so I'm still not certain how I feel about
> copying the behavior for nonempty?, but Bertram does have some basis
> for it. :)
>
> The rationale behind this is then the ability to say:
>
>   my_variable.nonzero? || default_value
>   my_variable.notempty? || default_value
>
> If my variable holds a non-zero/non-empty value, the original value is
> kept; if it holds a zero or an empty string, the default value is used
> (by returning nil). I'll admit this usage does seem handy, but the
> name of the methods don't reveal this "feature", which I think is a
> flaw. Just like you, I had *thought* that nonzero? and notempty? would
> be equivalent to !zero? and !empty?, respectively, because of the
> name.
>
> In the end, I'm not opposed to having *a* method with this
> functionality, and by analogy to nonzero?, the name bears a measure of
> consistency, but I'd still prefer a more revealing name for the
> method.

This may be a little off beat, but I wonder if Ruby's use of anything
but nil and false as true, might not be taken a step further. And
rather any object could have a state of true or false. Then conditions
could use this state rather than a type, which seems to me to fit
better with duck-typing. In other words

  x = ""
  x.empty?  #=> ""
  x.true?  #=> true

  y = "123"
  y.empty?  #=> "123"
  y.true?  #=> false

  x ? 1 : 0  #=> 1
  y ? 1 : 0  #=> 0

I'm not sure the full ramifications of this, but it a least seems
quite interesting at first glance.

T.

from Marcel Molina, Wed Mar 21 20:41:35 -0500 2007

On Wed, Mar 21, 2007 at 08:33:33PM -0500, transfire@gmail.com wrote:
> A comment about: RCR 9: Add String#notempty? method
> was sent by Trans  Onoma.
> 
> To send a comment, reply to this mail.  Please trim all unnecessary
> lines.
> 
> You can view RCR 9 at:
> https://rcrchive.net/rcrs/9
> 
> This may be a little off beat, but I wonder if Ruby's use of anything
> but nil and false as true, might not be taken a step further. And
> rather any object could have a state of true or false. Then conditions
> could use this state rather than a type, which seems to me to fit
> better with duck-typing. In other words
> 
>   x = ""
>   x.empty?  #=> ""
>   x.true?  #=> true
> 
>   y = "123"
>   y.empty?  #=> "123"
>   y.true?  #=> false
> 
>   x ? 1 : 0  #=> 1
>   y ? 1 : 0  #=> 0
> 
> I'm not sure the full ramifications of this, but it a least seems
> quite interesting at first glance.

At the risk of continuing off the beaten path, I've thought about a similar
idea whereby Object would have a to_bool method (returning true) and then
NilClass and FalseClass would return false and self (respetively). Then
object in conditional contexts would implicitly be coerced by calling to_bool
similarly to the way blocks are coerced with to_proc.

marcel

from Trans Onoma, Wed Mar 21 21:00:04 -0500 2007

On 3/21/07, marcel@vernix.org <marcel@vernix.org> wrote:

> At the risk of continuing off the beaten path, I've thought about a similar
> idea whereby Object would have a to_bool method (returning true) and then
> NilClass and FalseClass would return false and self (respetively). Then
> object in conditional contexts would implicitly be coerced by calling to_bool
> similarly to the way blocks are coerced with to_proc.

Ah, nice!

One of the things this opens up is the ability to do full
method-probing and dynamic backtracking (halting-problem not
withstanding).

T.

from Yukihiro Matsumoto, Wed Mar 21 21:11:14 -0500 2007

In message "Re: [RCR] Add String#notempty? method"
    on Wed, 21 Mar 2007 20:41:35 -0500, marcel@vernix.org writes:

|At the risk of continuing off the beaten path, I've thought about a similar
|idea whereby Object would have a to_bool method (returning true) and then
|NilClass and FalseClass would return false and self (respetively). Then
|object in conditional contexts would implicitly be coerced by calling to_bool
|similarly to the way blocks are coerced with to_proc.

It is too risky to decrease performance of the language.

                                                        matz.

from Paul Brannan, Thu Mar 22 08:14:19 -0500 2007

On Wed, Mar 21, 2007 at 08:33:22PM -0500, transfire@gmail.com wrote:
> This may be a little off beat, but I wonder if Ruby's use of anything
> but nil and false as true, might not be taken a step further. And
> rather any object could have a state of true or false. Then conditions
> could use this state rather than a type, which seems to me to fit
> better with duck-typing. In other words
> 
>   x = ""
>   x.empty?  #=> ""
>   x.true?  #=> true
> 
>   y = "123"
>   y.empty?  #=> "123"
>   y.true?  #=> false

So calling #empty? would change the boolean state of y?  How would this
work in a multithreading environment?

> 
>   x ? 1 : 0  #=> 1
>   y ? 1 : 0  #=> 0
> 
> I'm not sure the full ramifications of this, but it a least seems
> quite interesting at first glance.

It sounds confusing to me.

Paul


from Trans Onoma, Thu Mar 22 09:04:27 -0500 2007

On 3/22/07, pbrannan@atdesk.com <pbrannan@atdesk.com> wrote:
> On Wed, Mar 21, 2007 at 08:33:22PM -0500, transfire@gmail.com wrote:
> > This may be a little off beat, but I wonder if Ruby's use of anything
> > but nil and false as true, might not be taken a step further. And
> > rather any object could have a state of true or false. Then conditions
> > could use this state rather than a type, which seems to me to fit
> > better with duck-typing. In other words
> >
> >   x = ""
> >   x.empty?  #=> ""
> >   x.true?  #=> true
> >
> >   y = "123"
> >   y.empty?  #=> "123"
> >   y.true?  #=> false
>
> So calling #empty? would change the boolean state of y?  How would this
> work in a multithreading environment?

Hmm.. I guess it would be thread critical. More efficiency issues.

> It sounds confusing to me.

Maybe so. Interesting doesn't necessarily preclude confusing. :-)

T.


Return to top

Copyright © 2006, Ruby Power and Light, LLC