トップ «前の日記(2009-05-27) 最新 次の日記(2009-05-29)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2009-05-28

_ !!という構文

次のようなコードがあって、一体なんだ? という話。

obj.foobar? !!baz

で、!!という演算子があるかと思ってGoogleで検索したら、いきなり「!! に一致する情報は見つかりませんでした。」と言われる、即座に。

おれの予想。

きっと、obj#foobar?の実装が腐っていて、苦肉の策ではなかろうか?

たとえば、次のようになっている。Javaプログラマとかだとやってもそれほどおかしかない。

def foobar?(o)
  o == true
end

もし、引数がTrueClassのインスタンスかどうかを判定する目的のメソッドであれば、もちろん正しい実装ではある。

でも、真かどうかを判定しているなら、だめだね。

正しく実装すると

def foobar?(o)
  o != nil || o != false
end

でも、ちょっと冗長だ。単純に、

def foobar?(o)
  o
end

でいいじゃん。でも、いずれにしても、== trueとか書いてあるから、!!(否定によってfalseとなり、それを否定することでtrueとなる)としてTrueClassのインスタンスに変換してから引数としてるんじゃないかな。

いずれにしてもだけど、trueという特殊変数は戻り値、メソッドの引数とかにしか利用しないほうが良い。条件式に記述していたら、たいていは潜在的なバグだと言っても良さそうだ。もちろん == falseというのも、nilを考慮していないからだめだけど。

で、そういう怪しい可能性があるメソッドの引数なので、!!二重否定してTrueClassのインスタンス(あるいはFalseClassのインスタンス)に変換してんじゃないかなぁ、

似たようなのに、COMのC++コンポーネントがVBから正しく呼べないTRUE問題ってのもあったな。

HRESULT STDCALL FooBar(LONG baz)
{
  if (baz == TRUE)
    ...
  return S_OK;
}

となっているのを、

Set obj = CreateObject("FooBar")
obj.FooBar True

とか呼び出すケース。VBのBooleanはVARIANT_BOOL(short)で、TrueはVARIANT_TRUE(-1)だということを、C++小僧が知らないという話。

結局、ベストプラクティスとして、偽(0)かどうかで判定するというのが正解だろう。

HRESULT STDCALL FooBar(LONG baz)
{
  if (baz)
    ...
  return S_OK;
}

しかも、この方が==演算子とか書かなくて済むだけ簡潔だ。

_ おれは世界一不幸な少年かも知れないが

動くな、死ね、甦れ!【字幕版】 [VHS](ヴィターリー・カネフスキー)

かって、VHSでは出ていたのか……

本日のツッコミ(全2件) [ツッコミを入れる]
_ naruse (2009-05-28 02:58)

foobar?の実相としては、条件演算子が使えるなら、o ? true : falseが一番楽じゃないですかね。<br>また、仮説としては、foobar?の結果がfalseとnilで違うとか、0も偽になっちゃうとか。

_ arton (2009-05-28 03:08)

条件演算子は楽ですね。でも、true、falseって使わなくてもいいんじゃない? ってのが趣旨だから、単に「o」ってのがこの場合はいいと思うんだけど。0が偽になってたら、!!ってやってもtrueだからちょっと違うような。<br>というか、真偽値と == でtrue/falseを比較するって、どのあたりの言語の習慣なのかなぁ。Cじゃないし、Javaでもないし、不思議なんだよね。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|

ジェズイットを見習え