# Assignment operator that treats empty and nil as the same thing

**URL:** <https://www.ruby-forum.com/t/assignment-operator-that-treats-empty-and-nil-as-the-same-thing/147263>\
**Category:** Ruby\
**Created:** [August 30, 2008, 12:05am UTC](https://www.ruby-forum.com/t/assignment-operator-that-treats-empty-and-nil-as-the-same-thing/147263 "2008-08-30T00:05:39Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 30, 2008, 12:05am UTC](https://www.ruby-forum.com/t/assignment-operator-that-treats-empty-and-nil-as-the-same-thing/147263/1 "2008-08-30T00:05:39Z")

</div>

### test1

otest = {};  
otest[‘first\_name’] ||= ‘homer’;  
puts otest.inspect;

### test2

otest = {‘first\_name’=\>’’};  
otest[‘first\_name’] ||= ‘homer’;  
puts otest.inspect;

Problem: test1 produces the correct output, but test2 produces  
unwanted output (the value remains as an empty string). I realize that  
ruby treats the empty string as “true” … nevertheless I want to find  
an assignment operator in ruby that treats nil and empty exactly the  
same way, with the behavior shown in test1.

Question: Is there a way to do this in ruby _without_ resorting to an  
if statement or some other construct such as:

otest[‘first\_name’] = (otest[‘first\_name’].empty?) ‘homer’ :  
otest[‘first\_name’];

I would like to handle this with a _single_ assignment operator, just  
like you can do in test1.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 30, 2008, 1:05am UTC](https://www.ruby-forum.com/t/assignment-operator-that-treats-empty-and-nil-as-the-same-thing/147263/2 "2008-08-30T01:05:46Z")

</div>

removed\_email\_address@domain.invalid wrote:

> I would like to handle this with a _single_ assignment operator, just  
> like you can do in test1.

There is no such operator in Ruby. You have to make an if statement or  
something. Also remember that if the value is nil, calling empty? on it  
raises an error, so you have to check first for nil? and then for  
empty?.

You can make it a bit easier with something like this:

class Object  
def nothing?  
if nil?  
true  
elsif respond\_to? :empty? and empty?  
true  
elsif respond\_to? :zero? and zero?  
true  
else  
false  
end  
end  
end

You won’t have to check both conditions now.

TPR.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 30, 2008, 1:55am UTC](https://www.ruby-forum.com/t/assignment-operator-that-treats-empty-and-nil-as-the-same-thing/147263/3 "2008-08-30T01:55:39Z")

</div>

removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Problem: test1 produces the correct output, but test2 produces
> 
> I would like to handle this with a _single_ assignment operator, just  
> like you can do in test1.

Would it suffice to subvert Hash in such a way that the value of an  
element whose value is the empty string is reported as nil?

class Hash  
alias\_method “origfetch”, “[]”  
def   
result = origfetch(what)  
if result == ‘’  
nil  
else  
result  
end  
end  
end

h = {“hey”=\>“”, “ho”=\>“ha”}  
h[“hey”] ||= “homer”  
p h

If that’s too strong, you can devise your own function:

class Hash  
def set\_if\_empty(k,v)  
cur = self[k]  
if cur.nil? || cur == ‘’  
self[k] = v  
end  
end  
end

h = {“hey”=\>“”, “ho”=\>“ha”}  
h.set\_if\_empty(“hey”, “homer”)  
p h

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 30, 2008, 4:25am UTC](https://www.ruby-forum.com/t/assignment-operator-that-treats-empty-and-nil-as-the-same-thing/147263/4 "2008-08-30T04:25:22Z")

</div>

On Aug 29, 6:01 pm, “removed\_email\_address@domain.invalid” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Problem: test1 produces the correct output, but test2 produces
> 
> I would like to handle this with a _single_ assignment operator, just  
> like you can do in test1.

The problem is that you think that otest['first\_name] is nil in both  
tests when you try the conditional assignment. As the following code  
shows it’s only nil the first time; the second time it’s (an empty)  
String.

otest = {};  
puts otest[‘first\_name’] .class.to\_s  
otest[‘first\_name’] ||= ‘homer’;  
puts otest.inspect;

### test2

otest = {‘first\_name’=\>‘’};  
puts otest[‘first\_name’] .class.to\_s  
otest[‘first\_name’] ||= ‘homer’;  
puts otest.inspect;

HTH,  
Richard

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 30, 2008, 4:37am UTC](https://www.ruby-forum.com/t/assignment-operator-that-treats-empty-and-nil-as-the-same-thing/147263/5 "2008-08-30T04:37:40Z")

</div>

On Aug 29, 10:21 pm, RichardOnRails  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > ### test2
> > 
> > Question: Is there a way to do this in ruby _without_ resorting to an  
> > shows it’s only nil the first time; the second time it’s (an empty)  
> > otest[‘first\_name’] ||= ‘homer’;  
> > puts otest.inspect;
> 
> HTH,  
> Richard

Woops. I only glanced at your post when I responded. I only  
belatedly noticed that you understood the nil and and an empty string  
were involved. My apologies.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 30, 2008, 5:05am UTC](https://www.ruby-forum.com/t/assignment-operator-that-treats-empty-and-nil-as-the-same-thing/147263/6 "2008-08-30T05:05:43Z")

</div>

On Aug 29, 10:21 pm, RichardOnRails  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > ### test2
> > 
> > Question: Is there a way to do this in ruby _without_ resorting to an  
> > shows it’s only nil the first time; the second time it’s (an empty)  
> > otest[‘first\_name’] ||= ‘homer’;  
> > puts otest.inspect;
> 
> HTH,  
> Richard

Maybe I can redeem myself: Matt gave you a great solution in reopening  
the Hash definition. I recommend a minor improvement as follows:

class Hash  
alias\_method “orig\_fetch”, “[]”  
def   
result = orig\_fetch(what)  
result = nil if result == ‘’  
end  
end

### test1

otest = {}  
otest[‘first\_name’] ||= ‘homer’  
puts otest.inspect #= {“first\_name”=\>“homer”}

### test2

otest = {‘first\_name’=\>‘’}  
otest[‘first\_name’] ||= ‘homer’  
puts otest.inspect #= {“first\_name”=\>“homer”}

HTH,  
Richard

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 30, 2008, 12:33pm UTC](https://www.ruby-forum.com/t/assignment-operator-that-treats-empty-and-nil-as-the-same-thing/147263/7 "2008-08-30T12:33:30Z")

</div>

Xavier N. wrote:

> On Sat, Aug 30, 2008 at 5:00 AM, RichardOnRails  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > Maybe I can redeem myself: Matt gave you a great solution in reopening  
> > the Hash definition. I recommend a minor improvement as follows:
> > 
> > class Hash  
> > alias\_method “orig\_fetch”, “[]”  
> > def   
> > result = orig\_fetch(what)  
> > result = nil if result == ‘’  
> > end  
> > end
> 
> In my view that’s abusing open classes. Ruby has well-defined boolean  
> semantics, and Hash#[] is a fundamental method. People have  
> expectations about those ones.

I agree with that. But if it’s just one hash object that causes you  
problems, you can always change the method in the object’s eigenclass:

class \<\< your\_hash\_object  
alias\_method “origfetch”, “[]”  
def   
result = origfetch(what)  
if result == ‘’  
nil  
else  
result  
end  
end  
end

This way you won’t break the existing functionality for other hashes.

Or you could simply extend the class, modify the method in the  
descendant class, and make all your hashes instances of the descendant  
class.

TPR.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 30, 2008, 6:00am UTC](https://www.ruby-forum.com/t/assignment-operator-that-treats-empty-and-nil-as-the-same-thing/147263/8 "2008-08-30T06:00:39Z")

</div>

On Sat, Aug 30, 2008 at 5:00 AM, RichardOnRails  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Maybe I can redeem myself: Matt gave you a great solution in reopening  
> the Hash definition. I recommend a minor improvement as follows:
> 
> class Hash  
> alias\_method “orig\_fetch”, “[]”  
> def   
> result = orig\_fetch(what)  
> result = nil if result == ‘’  
> end  
> end

In my view that’s abusing open classes. Ruby has well-defined boolean  
semantics, and Hash#[] is a fundamental method. People have  
expectations about those ones.

In this case I think it could be better just to program explicitly  
your particular logic, either by hand, or in an clear separate method  
set\_if\_blank(key, value). I believe that one may be added to Hash if  
it deserves it in your app.
