Hatena::Groupbugrammer

蟲!虫!蟲!

Esehara Profile Site (by Heroku) / Github / bookable.jp (My Service)
過去の記事一覧はこちら

なにかあったら「えせはら あっと Gmail」まで送って頂ければ幸いです。
株式会社マリーチでは、Pythonやdjango、また自然言語処理を使ったお仕事を探しています

 | 

2011-10-18

[]グルーのパラドックスを実感するため、Trlse(True + False)を実装する(Python) 00:39

 Pythonメタプログラミングすることにより、いわゆる「パラドックス」を実感するという、ほぼシリーズみたいな形になっている、このブログ。今回はMongoDBインストールしていて、やたらと長い時間待たされるので、その間に「グルーのパラドックス」というものを紹介しておきましょう。

グルーのパラドックスとは何か

 グルーのパラドックスとは、グッドマンという哲学者が考えたパラドックス。このパラドックスの趣旨は、帰納法で考えると、どっちも同じくらい論証されているのにも関わらず、異なる結果を導き出してしまう」というのが趣旨です。

 まず、グルーという概念を考えます。グルーとは、「ある時点以前まで観察された緑のもの、ある時点以降まで観察された青のもの」という言い方をします。詳しくはWikipediaを見てもらえればいいかなと。

 例えば、エメラルドを考えてみましょう。「エメラルドは緑」という考え方が一般的だと思うのですけど、これは同時に「エメラルドはグルー」という言い方も出来てしまう。すると、不思議なことに、ある時点を境目に、「エメラルドは緑」というのは真なのにも関わらず、「エメラルドはグルーではない」というのも真になるということになります。

 帰納法とは何か、といえばモノを列挙して確認していく論法のことです。例えば「あのカラスも黒い、このカラスも黒い。従って、カラスは黒いものである」という論証のことです。だから、同時に「エメラルドは緑である」という確認は、ある時点までは「エメラルドはグルーである」という確認と同じくらい論証されてしまうわけです。

そのTrue、実はTrue + Falseじゃない?

 しかし、これは内部で定義が変わっているわけではありません。内部で定義が変わっていると考えるならば、「エメラルドが緑である」であり「エメラルドはグルーである」というのが、ある時点を境目に「エメラルドは緑である」と「エメラルドはグルーではない」というように分かれるのではなく、「ある時点のエメラルドはグルーであったが、これから見られるエメラルドはグルーではない」ということを説明したかったようです。

 なにやら混乱してきましたね。

 そこで、新しいBooleanを考えましょう。普通、ある評価が正しければTrue、ある評価が間違って入れば偽を返すというのがBooleanです。例えば 1 + 1 == 2ならTrue、1 + 3 == 5ならFalse、といったように返していきます。

 しかし、ある頭のおかしい青年がやってきて、こう述べます。「あなたが使っているそのTrueは、実はTrueではなく、ある関数が呼び出される以前の評価はTrue、ある関数が呼び出される以降の評価はFalseを意味する"Trlse"なのだ」と言い出したらどうでしょう。たぶんコンピューターサイエンスあたりで論破することは可能なのかもしれませんが、かれの言い分に乗ってみましょう。

Trlseの実装(間違い編)

 さて、まず「グルーのパラドックス」の誤解から考えます。つまり、内部で定義が書き換わっている場合を考えましょう。

def Trlse():
    global True
    True = 0

 これでおしまい。

 まず、Pythonの場合、False/Trueというのは、内部では0と1で管理されています。だから、例えば……

>>> (1 == 1) * 2
2
>>> (1 == 2) * 2
0
>>> 

 といったことが可能になります。

 そして、PythonはこのTrueが書き換え可能だったりします。つまり、任意の数を当てはめることが出来るわけです。とすると、TrueをFalseとして定義するとするならば、単純に数字の0をTrueとして代入してあげればいいわけです。

>>> (1 == 1) == True
True
>>> (1 == 2) == False
True
>>> Trlse()
>>> (1 == 1) == True
False
>>> (1 == 2) == True
True

 見事に書き換わってしまいました。

 しかし、これはちょっとおかしいんじゃないか。だって、内部で指し示すものが変わってしまうとするならば、今までの帰納法の論証自体成立しなくなるのでは?

 そうですね。ですから、もしこのパラドックスを成立させたければ、「いままで評価した式はTrue、これから評価する式はFalse」というようにしなければいけません。

Eval_Trlse の実装

 さて、メタプログラミングをするときの鉄則は一つで、要するに「予約語以外の全ては書き換えられる可能性を考える」ということです。そこで、このパラドックスを考えるなら、どんな関数を書き換えるのがいいかなと考えたら、ちょうどいいものがありました。

 それはevalです。

 evalは文字列Pythonの式として評価する関数です。例えば

>>> eval("1 == 1")
True
>>> eval("1 == 2")
False

 といったように。問題は、いままで評価した式というのを、何らかの形で残しておかなければいけないので、evalのように、文字列を渡してくれるものはかなり都合がいいわけです。

 それではさっそく実装してみましょう。

 ここでの実装は、evalに五回評価させた以降は、TrueはFalseを返し、FalseはTrueを返す関数に書き換えてしまいましょう。

import copy
pre_eval = copy.copy(eval)
eval_list = []
def eval_trlse(x):
    if len(eval_list) < 5:
        eval_list.append((x,pre_eval(x)))
        return pre_eval(x)
    else:
        for list in eval_list:
            if x == list[0]:
                return list[1]
        return not pre_eval(x)
eval = copy.copy(eval_trlse)

 上記でやっているのは、evalをeval_trlseの関数として書き換えるということですね。これを実行してみると……

>>> eval("1 == 1")
True
>>> eval("1 == 2")
False
>>> eval("2 == 2")
True
>>> eval("2 == 3")
False
>>> eval("3 == 3") 
False
>>> eval("3 == 4") #これ以降は逆転する
True
>>> eval("3 == 5")
True
>>> eval("1 == 1") #以前に評価したものなので、前の評価を返す
True

 さて、これで五回目までは、evalが使っているTrueが"True"なのか、それとも"Trlse"なのかわからなくなりました。

 このように、「帰納法では恣意的な結論が導きだせるのではないか」というのが、グルーのパラドックスなのでした。

 それじゃ、mongoDBをいじってきます。

mzouauvnsximzouauvnsxi2011/11/04 03:29BiNTNv <a href="http://cladigegrvur.com/">cladigegrvur</a>

lmbgjdrlmbgjdr2011/11/06 04:29GUXNVe , [url=http://utikdercilxn.com/]utikdercilxn[/url], [link=http://lnbqvhgupwgl.com/]lnbqvhgupwgl[/link], http://cfbntnkwglud.com/

 |