Pythonでlambdaをいじる。ちょっと闇なswitch編


結局やりたいことは、

  • スイッチの古い状態と新しい状態とプレイヤーの状態から次の動作を決めて出力し、
  • 新しい状態を古い状態として保存する、

の繰り返しです。
~if~else~でも構築できるんだけど、条件が多いと書きにくいし、見てもよくわからないものになってしまいそう。
スイッチ的なものがあればなあ。ってそもそもPythonにはswitchないし...
そこをかんがえてみました。

前回のクイックソートを例に。

通常のdef関数定義


def qs( xs ) :
        le = [x for x in xs[1:] if x<=xs[0] ]
        gt = [x for x in xs[1:] if x>xs[0] ]
        if xs == []:
                return []
        else:
                return qs( le ) + [ xs[0] ] + qs( gt )

lambda式で関数定義


qs=(lambda xs :
    (lambda
        le = [x for x in xs[1:] if x<=xs[0] ] ,
        gt = [x for x in xs[1:] if x>xs[0] ] :
        [] if xs == [] else
        qs( le ) + [ xs[0] ] + qs( gt )
    )()
)

これをスイッチ風にします。

まず準備。

box=lambda *x:x    #タプルに入れる
unbox=lambda x:x[-1]    #最後の要素を返す
do=box             #良さげな名前にする
switch=unbox         #同上
これを使います。するとこんな風になります。

qs=(lambda xs :
    (lambda
        le = [x for x in xs[1:] if x<=xs[0] ] ,
        gt = [x for x in xs[1:] if x>xs[0] ] :
        switch(
                do( [] ) if xs == [] else False
                or
                do( qs( le ) + [ xs[0] ] + qs( gt ) )
        )
    )()
)
条件が少ないので無駄に字が増えただけかも...
動作が先で条件が後だし...変...

でも、何となくswitchブロックに見えません?

switch()の中に、

do(式1,式2,...)if 条件式 else False
のかたまりをorでいくつもつなげていくことができます。
 最後にすべてのifが偽になった時の処理をdo(式1,式2,...)で書きます。
do(式1,式2,...)の中味は順番に評価されます。
その結果がタプルとしてswitch()に渡され、タプルの最後の値が返ります。

switchとdoには特に意味はありません。ヒト的には何となくそれっぽいかなと思って変えてみました。
名前から想像する機能はありません。
機能的にはunbox(取り出す)とbox(箱に入れる)です。
真の場合の値をタプルで包んだ(box)三項演算をorでつないで、最後にタプルから取り出す(unbox)
っていえば分かりやすいでしょうか?
タプルで包むことで値がorの制御に影響しなくなります。

見た目はじゅうぶん闇だけど、意外と基本的な機能でできちゃった...(無理しなかったからだけどね)...

使ってみてまた変えるかも。

コメント