Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

正オブジェクトの否定の否定はTrue

数値や文字列、selfといった正オブジェクトの否定の否定はTrueなのです!
...私も最初スクリプトを読んだ時は何事かと思いましたが...
pryで挙動を見ると意味を理解していただけるかと...

self
#=> main

!self
#=> false

!!self
#=> true

_人人人人人人人_
> 突然のTrue <
 ̄Y^Y^Y^Y^Y^Y ̄

他のオブジェクトでも挙動は同じです

"hoge"
#=> "hoge"

!"hoge"
#=> false

!!"hoge"
#=> true

1
#=> 1

!1
#=> false

!!1
#=> true

逆に、負のオブジェクトは否定されるとTrue、更に否定でfalseになります。

!!false
#=> false

これを生かしたのがActiveSupportのObject#blank?です。

class Object
  # An object is blank if it's false, empty, or a whitespace string.
  # For example, '', '   ', +nil+, [], and {} are all blank.
  #
  # This simplifies
  #
  #   address.nil? || address.empty?
  #
  # to
  #
  #   address.blank?
  #
  # @return [true, false]
  def blank?
    respond_to?(:empty?) ? !!empty? : !self
  end

  # An object is present if it's not blank.
  #
  # @return [true, false]
  def present?
    !blank?
  end
##中略
end

empty?メソッドが何かを返してくれれば、それを否定(#!)します。
何か存在すればfalseを返します。
falseの否定はtrue...。
empty?が無い場合はselfを否定する事でfalseを取り出します。*1
というわけで、少なくとも存在している場合はtrueを返してくれるわけです。
ついでに、モノが存在しているか確認するpresent?は!blank?と男前な実装になっています。
...このクラス、ちょっと人の事否定しすぎじゃないですかねぇ...?

追記(2016/05/03)

Chromium上でJavaScriptも同様の挙動になる事を確認しました。

*1:実際にはパフォーマンス対策なのかNil、False、True、Numericは専用にblank?を実装し、Array、Hash、Stringはempty?メソッドエイリアスしていたりしますが...