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
Which gives us this result:
![](https://digitalpress.fra1.cdn.digitaloceanspaces.com/xhtzjbw/2021/02/Screenshot-from-2021-02-20-15-35-42.png)
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
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).