DEV Community

Rich Steinmetz
Rich Steinmetz

Posted on • Originally published at richstone.io on

Ruby's not keyword is not not but ! (not)

Ruby's not keyword is not not but ! (not)

The title is confusing enough, so I don't want to bore you you with words today, let's better listen to some deep-sounding Rspec code... 🎵🎶

# ~/code/ruby/rubys_not_is_not_not_but_!_(not)_spec.rb

require './rubys_not_is_not_not_but_!_(not)'

RSpec.describe 'Ruby\'s not keyword' do
  let(:banger) { Banger.new }
  let(:naysayer) { Naysayer.new }

  context 'when ! is overriden' do
    it 'returns whatever value is returned by !' do
      expect(!banger).to eq :bang
      expect((not banger)).to eq :bang
    end

    it 'also returns the overriding\'s return value when called on the instance' do
      expect(banger.!).to eq :bang
    end
  end

  context 'when not is overriden' do
    it 'returns the overriding\'s return value when called on the instance' do
      expect(naysayer.not).to eq :nay
    end

    context 'but when used in the classical way before the message' do
      it 'evaluates a truthy value to false (as it always does)' do
        expect((not naysayer)).to eq false
      end
    end
  end
end

Enter fullscreen mode Exit fullscreen mode
Live test-driven, read tests first

Which gives us this result:

Ruby's not keyword is not not but ! (not)

And of course you are curious how it's implemented:

# ~/code/ruby/rubys_not_is_not_not_but_!_(not).rb

class Banger
  def !
    :bang
  end
end

class Naysayer
  def not
    :nay
  end
end
Enter fullscreen mode Exit fullscreen mode
Check this masterful code on GitHub if you don't believe

The Moral

As you can read from the docs, Ruby's ! can be overriden so that it will even return the overriding's value when used in front of a message (like ! message(), but the not keyword overridings only have effect on the instance's return value (e.g. instance.not()).

So the moral of the story is that not uses ! somehow under the hood because when ! is overriden it has also an effect on not.

This being said, they still are not aliases since they differ a tad in functionality (namely, in precedence).


Comments or questions? Just tweet it out to me!
Tweet

Want to get new chunks in your inbox? Hit the evanescent Subscribe button somewhere here 👇👉

Top comments (0)